Repository: trafodion
Updated Branches:
  refs/heads/master e618aaf3d -> 360427c20


[TRAFODION-2974] Make event log reader and JDBC real TMUDFs

Roberta pointed out that we have two predefined UDFs, EVENT_LOG_READER
and JDBC, where the system administrator should have the ability to
control who can execute these functions.

To do this, these two UDFs cannot be "predefined" UDFs anymore, since
those don't have the metadata that's required for doing grant and
revoke.

Roberta also pointed out that the JDBC UDF should refuse to connect to
the T2 driver, for security reasons.

The fix leaves the predefined TMUDFs in place, for now, they will be
removed in R2.4 (see TRAFODION-2975).

The new "real" TMUDFs are in the "_LIBMGR_" schema, mostly for
convenience, as this schema has other UDFs that are created when
Trafodion is initialized.


Project: http://git-wip-us.apache.org/repos/asf/trafodion/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafodion/commit/562a7bdf
Tree: http://git-wip-us.apache.org/repos/asf/trafodion/tree/562a7bdf
Diff: http://git-wip-us.apache.org/repos/asf/trafodion/diff/562a7bdf

Branch: refs/heads/master
Commit: 562a7bdf95e2cee26e9f77b9269c05b8c2ad162a
Parents: 75c7b39
Author: Hans Zeller <hzel...@apache.org>
Authored: Thu Mar 1 17:03:01 2018 +0000
Committer: Hans Zeller <hzel...@apache.org>
Committed: Thu Mar 1 17:14:00 2018 +0000

----------------------------------------------------------------------
 core/sql/bin/SqlciErrors.txt                    |   1 +
 core/sql/common/ComSmallDefs.h                  |   1 +
 .../java/org/trafodion/libmgmt/JDBCUDR.java     | 721 +++++++++++++++++++
 core/sql/optimizer/BindRelExpr.cpp              |  12 +
 core/sql/regress/udr/EXPECTED002                |  97 ++-
 core/sql/regress/udr/TEST002                    |  58 +-
 core/sql/sqlcomp/CmpSeabaseDDL.h                |   1 +
 core/sql/sqlcomp/CmpSeabaseDDLroutine.cpp       | 116 ++-
 core/sql/sqlcomp/CmpSeabaseDDLroutine.h         |  96 ++-
 .../java/org/trafodion/sql/udr/LmT2Driver.java  |  12 +
 .../org/trafodion/sql/udr/predef/JDBCUDR.java   |  33 +-
 11 files changed, 1104 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/bin/SqlciErrors.txt
----------------------------------------------------------------------
diff --git a/core/sql/bin/SqlciErrors.txt b/core/sql/bin/SqlciErrors.txt
index c79010b..ca2625f 100644
--- a/core/sql/bin/SqlciErrors.txt
+++ b/core/sql/bin/SqlciErrors.txt
@@ -1331,6 +1331,7 @@ $1~String1 --------------------------------
 4320 ZZZZZ 99999 BEGINNER MAJOR DBADMIN Stream access is not allowed on 
multi-partitioned table or index, when flag ATTEMPT_ASYNCHRONOUS_ACCESS is set 
to OFF. Object in scope: $0~TableName.
 4321 ZZZZZ 99999 BEGINNER MAJOR DBADMIN An embedded update/delete is not 
allowed on a partitioned table, when flag ATTEMPT_ASYNCHRONOUS_ACCESS is set to 
OFF. Object in scope: $0~TableName.
 4322 0A000 99999 BEGINNER MAJOR DBADMIN A column with BLOB datatype cannot be 
used in this clause or function.
+4323 ZZZZZ 99999 BEGINNER MAJOR DBADMIN Use of predefined UDF $0~String0 is 
deprecated and this function will be removed in a future release. Please use 
the function with the same name in schema TRAFODION."_LIBMGR_" instead. You may 
need to issue this command first: INITIALIZE TRAFODION, UPGRADE LIBRARY 
MANAGEMENT.
 4330 ZZZZZ 99999 BEGINNER MAJOR DBADMIN An invalid audit compression option 
$0~Int0 was used in the call to INTERPRET_AS_ROW.
 4331 ZZZZZ 99999 BEGINNER MAJOR DBADMIN KEY_RANGE_COMPARISON of partitioning 
keys on hash partitioned table $1~TableName is not allowed.
 4332 ZZZZZ 99999 BEGINNER MAJOR DBADMIN Table $1~TableName not exposed. Tables 
in scope: $2~string0.

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/common/ComSmallDefs.h
----------------------------------------------------------------------
diff --git a/core/sql/common/ComSmallDefs.h b/core/sql/common/ComSmallDefs.h
index b6baf11..02df604 100644
--- a/core/sql/common/ComSmallDefs.h
+++ b/core/sql/common/ComSmallDefs.h
@@ -193,6 +193,7 @@ typedef NABoolean               ComBoolean;
 // Procedures are defined in CmpSeabaseDDLroutine.h
 #define SEABASE_LIBMGR_SCHEMA "_LIBMGR_"
 #define SEABASE_LIBMGR_LIBRARY "DB__LIBMGRNAME"
+#define SEABASE_LIBMGR_LIBRARY_CPP "DB__LIBMGR_LIB_CPP"
 
 // reserved column names for traf internal system usage
 #define TRAF_SALT_COLNAME "_SALT_"

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/lib_mgmt/src/main/java/org/trafodion/libmgmt/JDBCUDR.java
----------------------------------------------------------------------
diff --git a/core/sql/lib_mgmt/src/main/java/org/trafodion/libmgmt/JDBCUDR.java 
b/core/sql/lib_mgmt/src/main/java/org/trafodion/libmgmt/JDBCUDR.java
new file mode 100644
index 0000000..e75f603
--- /dev/null
+++ b/core/sql/lib_mgmt/src/main/java/org/trafodion/libmgmt/JDBCUDR.java
@@ -0,0 +1,721 @@
+/**********************************************************************
+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.
+**********************************************************************/
+
+/***************************************************
+ * A TMUDF that executes a generic JDBC query
+ * and returns the result of the one SQL statement
+ * in the list that produces results as a table-valued
+ * output
+ *
+ * Invocation (all arguments are strings):
+ *
+ * select ... from udf(JDBC(
+ *    <name of JDBC driver jar>, // file name of the JDBC driver jar, stored
+ *                               // in $TRAF_HOME/udr/public/external_libs
+ *    <name of JDBC driver class in the jar>,
+ *    <connection string>,
+ *    <user name>,
+ *    <password>,
+ *    <statement_type>,
+ *    <sql statement 1>
+ *    [ , <sql statements 2 ...n> ] )) ...
+ *
+ * The first 7 arguments are required and must be
+ * string literals that are available at compile
+ * time.
+ * Statement type:
+ *    'source': This statement produces a result
+ *              (only type allowed at this time)
+ *              (may support "target" to insert
+ *               into a table via JDBC later)
+ *
+ * Note that only one of the SQL statements can be
+ * a select or other result-producing statements.
+ * The others can perform setup and cleanup
+ * operations, if necessary (e.g. create table,
+ * insert, select, drop table).
+ *
+ * For an example, see file
+ * core/sql/regress/udr/TEST002.
+ ***************************************************/
+
+package org.trafodion.libmgmt;
+
+import org.trafodion.sql.udr.*;
+import java.sql.*;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Vector;
+import java.lang.Math;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+class JDBCUDR extends UDR
+{
+    // class used to connect, both at compile and at runtime
+    static class JdbcConnectionInfo
+    {
+        String driverJar_;
+        String driverClassName_;
+        String connectionString_;
+        String username_;
+        String password_;
+        boolean debug_;
+
+        Connection conn_;
+
+        public void setJar(String jar)
+                                                     { driverJar_ = jar; }
+        public void setClass(String className)
+                                         { driverClassName_ = className; }
+        public void setConnString(String connString)
+                                       { connectionString_ = connString; }
+        public void setUsername(String userName)
+                                                 { username_ = userName; }
+        public void setPassword(String password)
+                                                 { password_ = password; }
+        public void setDebug(boolean debug)            { debug_ = debug; }
+
+        public Connection connect() throws UDRException
+        {
+          try {
+            Path driverJarPath = Paths.get(driverJar_);
+
+            // for security reasons, we sandbox the allowed driver jars
+            // into $TRAF_HOME/udr/public/external_libs
+            driverJarPath = driverJarPath.normalize();
+            if (driverJarPath.isAbsolute())
+              {
+                if (! driverJarPath.startsWith(
+                                  LmUtility.getSandboxRootForUser(null)))
+                  throw new UDRException(
+                    38010,
+                    "The jar name of the JDBC driver must be a name relative 
to %s, got %s",
+                    LmUtility.getSandboxRootForUser(null).toString(),
+                    driverJar_);
+              }
+            else
+              driverJarPath = 
LmUtility.getExternalLibsDirForUser(null).resolve(
+                    driverJarPath);
+
+            // for security reasons we also reject the Trafodion T2
+            // driver (check both class name and URL)
+            if 
(driverClassName_.equals("org.apache.trafodion.jdbc.t2.T2Driver"))
+                throw new UDRException(
+                    38012,
+                    "This UDF does not support the Trafodion T2 driver class 
%s",
+                    driverClassName_);
+
+            if (LmT2Driver.checkURL(connectionString_))
+                throw new UDRException(
+                    38013,
+                    "This UDF does not support the Trafodion T2 driver URL %s",
+                    connectionString_);
+ 
+            // Create a class loader that can access the jar file
+            // specified by the caller. Note that this is only needed
+            // because the JDBC UDR is a predefined UDR and is loaded
+            // by the standard class loader. If it were a regular UDR,
+            // it would have been loaded by LmClassLoader and we would
+            // not need to create an LmClassLoader here.
+            LmClassLoader jdbcJarLoader = LmUtility.createClassLoader(
+                                               driverJarPath.toString(),0);
+
+            Driver d = (Driver) Class.forName(driverClassName_,
+                                              true,
+                                              jdbcJarLoader).newInstance();
+
+            // go through an intermediary driver, since the DriverManager
+            // will not accept classes that are not loaded by the default
+            // class loader
+            DriverManager.registerDriver(new URLDriver(d));
+            conn_ = DriverManager.getConnection(connectionString_,
+                                                username_,
+                                                password_);
+            return conn_;
+          }
+          catch (ClassNotFoundException cnf) {
+              throw new UDRException(
+                38020,
+                "JDBC driver class %s not found. Please make sure the JDBC 
driver jar %s is stored in %s. Message: %s",
+                driverClassName_,
+                driverJar_,
+                LmUtility.getSandboxRootForUser(null).toString(),
+                cnf.getMessage());
+          }
+          catch (SQLException se) {
+              throw new UDRException(
+                38020,
+                "SQL exception during connect. Message: %s",
+                se.getMessage());
+          }
+          catch (Exception e) {
+              if (debug_)
+                  {
+                      System.out.println("Debug: Exception during connect:");
+                      try { e.printStackTrace(System.out); }
+                      catch (Exception e2) {}
+                  }
+              throw new UDRException(
+                38020,
+                "Exception during connect: %s",
+                e.getMessage());
+          }
+        }
+
+        public Connection getConnection()                 { return conn_; }
+
+        public void disconnect() throws SQLException
+        {
+            conn_.close();
+            conn_ = null;
+        }
+    };
+
+    // list of SQL statements to execute
+    static class SQLStatementInfo
+    {
+        // list of SQL statements to execute
+        Vector<String> sqlStrings_;
+
+        // which of the above is the one that
+        // produces the table-valued result?
+        int resultStatementIndex_;
+
+        // prepared result-producing statement
+        PreparedStatement resultStatement_;
+
+        SQLStatementInfo()
+        {
+            sqlStrings_ = new Vector<String>();
+            resultStatementIndex_ = -1;
+        }
+
+        void addStatementText(String sqlText)
+        {
+            sqlStrings_.add(sqlText);
+        }
+
+        void addResultProducingStatement(PreparedStatement preparedStmt,
+                                         int resultStatementIndex)
+        {
+            resultStatement_ = preparedStmt;
+            resultStatementIndex_ = resultStatementIndex;
+        }
+
+        String getStatementText(int ix)    { return sqlStrings_.get(ix); }
+        PreparedStatement getResultStatement(){ return resultStatement_; }
+        int getNumStatements()              { return sqlStrings_.size(); }
+        int getResultStatementIndex()    { return resultStatementIndex_; }
+    };
+
+    // Define data that gets passed between compiler phases
+    static class JdbcCompileTimeData extends UDRWriterCompileTimeData
+    {
+        JdbcConnectionInfo jci_;
+        SQLStatementInfo sqi_;
+
+        JdbcCompileTimeData()
+        {
+            jci_ = new JdbcConnectionInfo();
+            sqi_ = new SQLStatementInfo();
+        }
+    };
+
+    static class URLDriver implements Driver {
+       private Driver driver_;
+       URLDriver(Driver d) { driver_ = d; }
+       public boolean acceptsURL(String u) throws SQLException {
+            return driver_.acceptsURL(u);
+       }
+       public Connection connect(String u, Properties p) throws SQLException {
+            return driver_.connect(u, p);
+       }
+       public int getMajorVersion() {
+            return driver_.getMajorVersion();
+       }
+       public int getMinorVersion() {
+            return driver_.getMinorVersion();
+       }
+       public DriverPropertyInfo[] getPropertyInfo(String u, Properties p) 
throws SQLException {
+            return driver_.getPropertyInfo(u, p);
+       }
+       public boolean jdbcCompliant() {
+            return driver_.jdbcCompliant();
+       }
+        public Logger getParentLogger() throws SQLFeatureNotSupportedException 
{
+            return driver_.getParentLogger();
+        }
+    }
+
+    JdbcConnectionInfo getConnectionInfo(UDRInvocationInfo info) throws 
UDRException
+    {
+        return ((JdbcCompileTimeData) info.getUDRWriterCompileTimeData()).jci_;
+    }
+
+    SQLStatementInfo getSQLStatementInfo(UDRInvocationInfo info) throws 
UDRException
+    {
+        return ((JdbcCompileTimeData) info.getUDRWriterCompileTimeData()).sqi_;
+    }
+
+
+    // default constructor
+    public JDBCUDR()
+    {}
+
+    // a method to process the input parameters, this is
+    // used both at compile time and at runtime
+    private void handleInputParams(UDRInvocationInfo info,
+                                   JdbcConnectionInfo jci,
+                                   SQLStatementInfo sqi,
+                                   boolean isCompileTime)
+                                             throws UDRException
+    {
+        int numInParams = info.par().getNumColumns();
+
+        // Right now we don't support table inputs
+        if (isCompileTime && info.getNumTableInputs() != 0)
+            throw new UDRException(
+              38300,
+              "%s must be called with no table-valued inputs",
+              info.getUDRName());
+
+        if (numInParams < 7)
+            throw new UDRException(
+              38310,
+              "Expecting at least 7 parameters for %s UDR",
+              info.getUDRName());
+
+        // loop over scalar input parameters
+        for (int p=0; p<numInParams; p++)
+            {
+                if (isCompileTime &&
+                    ! info.par().isAvailable(p))
+                    throw new UDRException(
+                      38320,
+                      "Parameter %d of %s must be a compile time constant",
+                      p+1,
+                      info.getUDRName());
+
+                String paramValue = info.par().getString(p);
+
+                switch (p)
+                    {
+                    case 0:
+                        jci.setJar(paramValue);
+                        break;
+
+                    case 1:
+                        jci.setClass(paramValue);
+                        break;
+
+                    case 2:
+                        jci.setConnString(paramValue);
+                        break;
+
+                    case 3:
+                        jci.setUsername(paramValue);
+                        break;
+
+                    case 4:
+                        jci.setPassword(paramValue);
+                        break;
+
+                    case 5:
+                        // Only statement type supported
+                        // so far is select, we may support insert later
+                        if (paramValue.compareToIgnoreCase("source") != 0)
+                            throw new UDRException(
+                              38330,
+                              "The only statement type supported so far is 
'source' in parameter 6 of %s",
+                              info.getUDRName());
+                        break;
+
+                    default:
+                        // SQL statement (there could be multiple)
+                        sqi.addStatementText(paramValue);
+                        break;
+
+                    }
+
+                if (isCompileTime)
+                    // add the actual parameter as a formal parameter
+                    // (the formal parameter list is initially empty)
+                    info.addFormalParameter(info.par().getColumn(p));
+            }
+
+        jci.setDebug(info.getDebugFlags() != 0);
+
+        // Prepare each provided statement. We will verify that
+        // only one of these statements produces result rows,
+        // which will become our table-valued output.
+        int numSQLStatements = sqi.getNumStatements();
+
+        // sanity check
+        if (numSQLStatements != numInParams-6)
+            throw new UDRException(383400, "internal error");
+
+        if (numSQLStatements < 1)
+            throw new UDRException(383500, "At least one SQL statement must be 
given in parameters 6 and following");
+
+        if (isCompileTime)
+        {
+            // walk through all statements, check whether they are
+            // valid by preparing them, and determine which one is
+            // the one that generates a result set
+            String currentStmtText = "";
+            try
+            {
+                jci.connect();
+
+                for (int s=0; s<numSQLStatements; s++)
+                {
+                    currentStmtText = sqi.getStatementText(s);
+                    // System.out.printf("Statement to prepare: %s\n", 
currentStmtText);
+                    PreparedStatement preparedStmt =
+                            
jci.getConnection().prepareStatement(currentStmtText);
+                    // if (preparedStmt != null)
+                    //    System.out.printf("Prepare was successful\n");
+                    ParameterMetaData pmd = 
preparedStmt.getParameterMetaData();
+                    if (pmd != null && pmd.getParameterCount() != 0)
+                        throw new UDRException(
+                                38360,
+                                "Statement %s requires %d input parameters, 
which is not supported",
+                                currentStmtText, pmd.getParameterCount());
+                    ResultSetMetaData desc = preparedStmt.getMetaData();
+
+                    int numResultCols = desc.getColumnCount();
+                    // System.out.printf("Number of output columns: %d", 
numResultCols);
+
+                    if (numResultCols > 0)
+                    {
+                        if (sqi.getResultStatementIndex() >= 0)
+                            throw new UDRException(
+                                    38370,
+                                    "More than one of the statements provided 
produce output, this is not supported (%d and %d)",
+                                    sqi.getResultStatementIndex()+1,
+                                    s+1);
+
+                        // we found the statement that is producing the result
+                        sqi.addResultProducingStatement(preparedStmt, s);
+
+                        // now add the output columns
+                        for (int c=0; c<numResultCols; c++)
+                        {
+                            String colName = desc.getColumnLabel(c+1);
+                            TypeInfo udrType = getUDRTypeFromJDBCType(desc, 
c+1);
+                            info.out().addColumn(new ColumnInfo(colName, 
udrType));
+                        }
+                    }
+                }
+                jci.disconnect();
+            }
+            catch (SQLException e)
+            {
+                throw new UDRException(
+                        38380,
+                        "SQL Exception when preparing SQL statement %s. 
Exception text: %s",
+                        currentStmtText, e.getMessage());
+            }
+        }
+    }
+
+    TypeInfo getUDRTypeFromJDBCType(ResultSetMetaData desc,
+                                    int colNumOneBased) throws UDRException
+    {
+        TypeInfo result;
+
+        final int maxLength = 100000;
+
+        int colJDBCType;
+
+        // the ingredients to make a UDR type and their default values
+        TypeInfo.SQLTypeCode      sqlType      = 
TypeInfo.SQLTypeCode.UNDEFINED_SQL_TYPE;
+        int                       length       = 0;
+        boolean                   nullable     = false;
+        int                       scale        = 0;
+        TypeInfo.SQLCharsetCode   charset      = 
TypeInfo.SQLCharsetCode.CHARSET_UCS2;
+        TypeInfo.SQLIntervalCode  intervalCode = 
TypeInfo.SQLIntervalCode.UNDEFINED_INTERVAL_CODE;
+        int                       precision    = 0;
+        TypeInfo.SQLCollationCode collation    = 
TypeInfo.SQLCollationCode.SYSTEM_COLLATION;
+
+        try {
+            colJDBCType = desc.getColumnType(colNumOneBased);
+            nullable = (desc.isNullable(colNumOneBased) != 
ResultSetMetaData.columnNoNulls);
+
+            // map the JDBC type to a Trafodion UDR parameter type
+            switch (colJDBCType)
+            {
+            case java.sql.Types.SMALLINT:
+            case java.sql.Types.TINYINT:
+            case java.sql.Types.BOOLEAN:
+                if (desc.isSigned(colNumOneBased))
+                    sqlType = TypeInfo.SQLTypeCode.SMALLINT;
+                else
+                    sqlType = TypeInfo.SQLTypeCode.SMALLINT_UNSIGNED;
+                break;
+
+            case java.sql.Types.INTEGER:
+                if (desc.isSigned(colNumOneBased))
+                    sqlType = TypeInfo.SQLTypeCode.INT;
+                else
+                    sqlType = TypeInfo.SQLTypeCode.INT_UNSIGNED;
+                break;
+
+            case java.sql.Types.BIGINT:
+                sqlType = TypeInfo.SQLTypeCode.LARGEINT;
+                break;
+
+            case java.sql.Types.DECIMAL:
+            case java.sql.Types.NUMERIC:
+                if (desc.isSigned(colNumOneBased))
+                    sqlType = TypeInfo.SQLTypeCode.NUMERIC;
+                else
+                    sqlType = TypeInfo.SQLTypeCode.NUMERIC_UNSIGNED;
+                precision = desc.getPrecision(colNumOneBased);
+                scale = desc.getScale(colNumOneBased);
+                break;
+
+            case java.sql.Types.REAL:
+                sqlType = TypeInfo.SQLTypeCode.REAL;
+                break;
+
+            case java.sql.Types.DOUBLE:
+            case java.sql.Types.FLOAT:
+                sqlType = TypeInfo.SQLTypeCode.DOUBLE_PRECISION;
+                break;
+
+            case java.sql.Types.CHAR:
+            case java.sql.Types.NCHAR:
+                sqlType = TypeInfo.SQLTypeCode.CHAR;
+                length  = Math.min(desc.getPrecision(colNumOneBased), 
maxLength);
+                charset = TypeInfo.SQLCharsetCode.CHARSET_UCS2;
+                break;
+
+            case java.sql.Types.VARCHAR:
+            case java.sql.Types.NVARCHAR:
+                sqlType = TypeInfo.SQLTypeCode.VARCHAR;
+                length  = Math.min(desc.getPrecision(colNumOneBased), 
maxLength);
+                charset = TypeInfo.SQLCharsetCode.CHARSET_UCS2;
+                break;
+
+            case java.sql.Types.DATE:
+                sqlType = TypeInfo.SQLTypeCode.DATE;
+                break;
+
+            case java.sql.Types.TIME:
+                sqlType = TypeInfo.SQLTypeCode.TIME;
+                break;
+
+            case java.sql.Types.TIMESTAMP:
+                sqlType = TypeInfo.SQLTypeCode.TIMESTAMP;
+                scale   = 3;
+                break;
+
+                // BLOB - not supported yet, map to varchar
+                // case java.sql.Types.BLOB:
+                // sqlType = TypeInfo.SQLTypeCode.BLOB;
+                // break;
+
+                // CLOB - not supported yet, map to varchar
+                // case java.sql.Types.CLOB:
+                // sqlType = TypeInfo.SQLTypeCode.CLOB;
+                // break;
+
+            case java.sql.Types.ARRAY:
+            case java.sql.Types.BINARY:
+            case java.sql.Types.BIT:
+            case java.sql.Types.BLOB:
+            case java.sql.Types.DATALINK:
+            case java.sql.Types.DISTINCT:
+            case java.sql.Types.JAVA_OBJECT:
+            case java.sql.Types.LONGVARBINARY:
+            case java.sql.Types.NULL:
+            case java.sql.Types.OTHER:
+            case java.sql.Types.REF:
+            case java.sql.Types.STRUCT:
+            case java.sql.Types.VARBINARY:
+                // these types produce a binary result, represented
+                // as varchar(n) character set iso88591
+                sqlType = TypeInfo.SQLTypeCode.VARCHAR;
+                length  = Math.min(desc.getPrecision(colNumOneBased), 
maxLength);
+                charset = TypeInfo.SQLCharsetCode.CHARSET_ISO88591;
+                break;
+
+            case java.sql.Types.LONGVARCHAR:
+            case java.sql.Types.LONGNVARCHAR:
+            case java.sql.Types.CLOB:
+            case java.sql.Types.NCLOB:
+            case java.sql.Types.ROWID:
+            case java.sql.Types.SQLXML:
+                // these types produce a varchar(n) character set utf8 result
+                sqlType = TypeInfo.SQLTypeCode.VARCHAR;
+                length  = Math.min(desc.getPrecision(colNumOneBased), 
maxLength);
+                charset = TypeInfo.SQLCharsetCode.CHARSET_UCS2;
+                break;
+            }
+        } catch (SQLException e) {
+            throw new UDRException(
+                    38500,
+                    "Error determinging the type of output column %d: ",
+                    colNumOneBased,
+                    e.getMessage());
+        }
+
+        result = new TypeInfo(
+                sqlType,
+                length,
+                nullable,
+                scale,
+                charset,
+                intervalCode,
+                precision,
+                collation);
+
+        return result;
+    }
+
+    // determine output columns dynamically at compile time
+    @Override
+    public void describeParamsAndColumns(UDRInvocationInfo info)
+        throws UDRException
+    {
+        // create an object with common info for this
+        // UDF invocation that we will carry through the
+        // compilation phases
+        info.setUDRWriterCompileTimeData(new JdbcCompileTimeData());
+
+        // retrieve the compile time data, we will do this for
+        // every compile phase
+        JdbcConnectionInfo jci = getConnectionInfo(info);
+        SQLStatementInfo   sqi = getSQLStatementInfo(info);
+
+        // process input parameters
+        handleInputParams(info, jci, sqi, true);
+   }
+
+    // override the runtime method
+    @Override
+    public void processData(UDRInvocationInfo info,
+                            UDRPlanInfo plan)
+        throws UDRException
+    {
+        // retrieve the compile time data, we will do this for
+        // every compile phase
+        JdbcConnectionInfo jci = new JdbcConnectionInfo();
+        SQLStatementInfo   sqi = new SQLStatementInfo();
+        int numCols = info.out().getNumColumns();
+
+        // process input parameters (again, now at runtime)
+        handleInputParams(info, jci, sqi, false);
+
+        int numSQLStatements = sqi.getNumStatements();
+        int numSQLResultSets = 0;
+        String stmtText = null;
+
+        try {
+            Connection conn = jci.connect();
+            Statement stmt = conn.createStatement();
+
+            for (int s=0; s<numSQLStatements; s++)
+            {
+                stmtText = sqi.getStatementText(s);
+
+                boolean hasResultSet = stmt.execute(stmtText);
+
+                if (hasResultSet)
+                {
+                    ResultSet rs = stmt.getResultSet();
+                    numSQLResultSets++;
+
+                    if (numSQLResultSets > 1)
+                        throw new UDRException(
+                                38700,
+                                "More than one result set returned by UDF %s",
+                                info.getUDRName());
+
+                    if (rs.getMetaData().getColumnCount() != numCols)
+                        throw new UDRException(
+                                38702,
+                                "Number of columns returned by UDF %s (%d) 
differs from the number determined at compile time (%d)",
+                                info.getUDRName(),
+                                rs.getMetaData().getColumnCount(),
+                                numCols);
+
+                    while (rs.next())
+                    {
+                        for (int c=0; c<numCols; c++)
+                        {
+                            TypeInfo typ = info.out().getColumn(c).getType();
+
+                            switch (typ.getSQLTypeSubClass())
+                            {
+                            case FIXED_CHAR_TYPE:
+                            case VAR_CHAR_TYPE:
+                                info.out().setString(c, rs.getString(c+1));
+                                break;
+
+                            case EXACT_NUMERIC_TYPE:
+                                info.out().setLong(c, rs.getLong(c+1));
+                                break;
+
+                            case APPROXIMATE_NUMERIC_TYPE:
+                                info.out().setDouble(c, rs.getDouble(c+1));
+                                break;
+
+                            case DATE_TYPE:
+                                info.out().setTime(c, rs.getDate(c+1));
+                                break;
+
+                            case TIME_TYPE:
+                                info.out().setTime(c, rs.getTime(c+1));
+                                break;
+
+                            case TIMESTAMP_TYPE:
+                                info.out().setTime(c, rs.getTimestamp(c+1));
+                                break;
+
+                            case LOB_SUB_CLASS:
+                                throw new UDRException(38710, "LOB parameters 
not yet supported");
+
+                            default:
+                                throw new UDRException(38720, "Unexpected data 
type encountered");
+
+                            } // switch
+
+                            if (rs.wasNull())
+                                info.out().setNull(c);
+                        } // loop over columns
+
+                        // produce a result row
+                        emitRow(info);
+
+                    } // loop over result rows
+                } // statement produces a result set
+            } // loop over statements
+            jci.disconnect();
+        } catch (SQLException e) {
+            throw new UDRException(
+                    38730,
+                    "Error preparing statement %s at runtime: %s",
+                    stmtText,
+                    e.getMessage());
+        }
+    }
+};

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/optimizer/BindRelExpr.cpp
----------------------------------------------------------------------
diff --git a/core/sql/optimizer/BindRelExpr.cpp 
b/core/sql/optimizer/BindRelExpr.cpp
index 7beaf9e..960b451 100644
--- a/core/sql/optimizer/BindRelExpr.cpp
+++ b/core/sql/optimizer/BindRelExpr.cpp
@@ -17226,6 +17226,18 @@ RelExpr *TableMappingUDF::bindNode(BindWA *bindWA)
           for (int i=0; i<getArity(); i++)
             result->child(i) = child(i);
 
+          if (opType == REL_TABLE_MAPPING_BUILTIN_LOG_READER ||
+              opType == REL_TABLE_MAPPING_BUILTIN_JDBC)
+            {
+              // The event log reader and JDBC TMUDFs are being migrated
+              // to real UDFs, use of the predefined UDFs is deprecated.
+              // Issue a warning. Eventually these predefined functions
+              // will be removed.
+              (*CmpCommon::diags())
+                << DgSqlCode(4323)
+                << DgString0(tmfuncName.getExposedNameAsAnsiString());
+            }
+
           // Abandon the current node and return the bound new node.
           // Next time it will reach this method it will call an
           // overloaded getRoutineMetadata() that will succeed.

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/regress/udr/EXPECTED002
----------------------------------------------------------------------
diff --git a/core/sql/regress/udr/EXPECTED002 b/core/sql/regress/udr/EXPECTED002
index 4a378ba..b5d92cb 100644
--- a/core/sql/regress/udr/EXPECTED002
+++ b/core/sql/regress/udr/EXPECTED002
@@ -6515,10 +6515,20 @@ the                                                     
   611
 
 --- 6344 row(s) selected.
 >>
->>-- some simple tests for the event_log_reader predefined TMUDF
+>>-- make sure the event_log_reader and jdbc UDFs are created (this
+>>-- should only be needed while we are developing Trafodion 2.3, in
+>>-- future releases the installer should do this automatically, by
+>>-- executing the upgrade command below)
+>>initialize trafodion, upgrade library management;
+
+--- SQL operation complete.
+>>
+>>-- some simple tests for the event_log_reader TMUDF
 >>-- (result of the UDF is not deterministic)
 >>select [last 0] * from udf(event_log_reader());
 
+*** WARNING[4323] Use of predefined UDF EVENT_LOG_READER is deprecated and 
this function will be removed in a future release. Please use the function with 
the same name in schema TRAFODION."_LIBMGR_" instead. You may need to issue 
this command first: INITIALIZE TRAFODION, UPGRADE LIBRARY MANAGEMENT.
+
 --- 0 row(s) selected.
 >>select [last 0] log_ts + interval '1' day,
 +>                severity || 'x',
@@ -6533,12 +6543,14 @@ the                                                     
   611
 +>                log_file_name,
 +>                log_file_line -1,
 +>                case when parse_status = ' ' then 'ok' else parse_status end
-+>from udf(event_log_reader('f'));
++>from udf("_LIBMGR_".event_log_reader('f'));
 
 --- 0 row(s) selected.
 >>select coalesce(min(log_file_node), 0) from udf(event_log_reader('f')) x
 +>where x.log_file_line <100;
 
+*** WARNING[4323] Use of predefined UDF X is deprecated and this function will 
be removed in a future release. Please use the function with the same name in 
schema TRAFODION."_LIBMGR_" instead. You may need to issue this command first: 
INITIALIZE TRAFODION, UPGRADE LIBRARY MANAGEMENT.
+
 (EXPR)     
 -----------
 
@@ -6554,7 +6566,7 @@ the                                                       
 611
 +>       max(log_file_line) as num_lines,
 +>       count(distinct query_id) num_query_ids,
 +>       sum(case when parse_status = ' ' then 0 else 1 end) num_parse_errors
-+>from udf(event_log_reader('f'))
++>from udf("_LIBMGR_".event_log_reader('f'))
 +>where log_file_name = 'master_exec_regr_999_99999.log';
 
 NUM_EVENTS            NUM_LINES    NUM_QUERY_IDS         NUM_PARSE_ERRORS
@@ -6565,7 +6577,7 @@ NUM_EVENTS            NUM_LINES    NUM_QUERY_IDS         
NUM_PARSE_ERRORS
 --- 1 row(s) selected.
 >>-- there are 22 events in 33 lines in this file, with 13 unique query ids 
 >>and 3 parse errors
 >>
->>select * from udf(event_log_reader('f'))
+>>select * from udf("_LIBMGR_".event_log_reader('f'))
 +>where log_file_name = 'master_exec_regr_999_99999.log'
 +>  and (log_file_line in (1,3,8,16,23) or parse_status <> ' ')
 +>order by log_file_line;
@@ -6590,33 +6602,46 @@ LOG_TS                      SEVERITY    COMPONENT
 >>-- some negative test cases
 >>prepare s from select * from udf(event_log_reader(10));
 
+*** WARNING[4323] Use of predefined UDF EVENT_LOG_READER is deprecated and 
this function will be removed in a future release. Please use the function with 
the same name in schema TRAFODION."_LIBMGR_" instead. You may need to issue 
this command first: INITIALIZE TRAFODION, UPGRADE LIBRARY MANAGEMENT.
+
 *** ERROR[11252] Expecting a character constant as first parameter of the call 
to TRAFODION.SCH.EVENT_LOG_READER (SQLSTATE 38222)
 
 *** ERROR[8822] The statement was not prepared.
 
 >>-- parameter must be a string
->>prepare s from select * from udf(event_log_reader(?));
+>>prepare s from select * from udf("_LIBMGR_".event_log_reader(?));
 
 *** ERROR[11151] Unable to use 'type' 'UNSUPPORTED TYPE' in a user-defined 
routine. Details: unsupported type class.
 
 *** ERROR[8822] The statement was not prepared.
 
 >>-- parameter must be available at compile time
->>prepare s from select * from udf(event_log_reader(table(select * from 
(values (1)) as x)));
+>>prepare s from
++>select *
++>from udf("_LIBMGR_".event_log_reader(table(select * from (values (1)) as 
x)));
 
-*** ERROR[11252] There should be no table-valued parameters to the call to 
TRAFODION.SCH.EVENT_LOG_READER, got 1 (SQLSTATE 38220)
+*** ERROR[11252] There should be no table-valued parameters to the call to 
TRAFODION."_LIBMGR_".EVENT_LOG_READER, got 1 (SQLSTATE 38220)
 
 *** ERROR[8822] The statement was not prepared.
 
 >>-- table-valued input not allowed
 >>prepare s from select query_id, log_file_name, parse_status
-+>from udf(event_log_reader());
++>from udf("_LIBMGR_".event_log_reader());
 
 *** ERROR[4001] Column LOG_FILE_NAME is not found.  Tables in scope: NONE.  
Default schema: TRAFODION.SCH.
 
 *** ERROR[8822] The statement was not prepared.
 
 >>-- log_file_name and parse_status columns not available without 'f' option
+>>prepare s from select * from udf(nosuchschema.event_log_reader());
+
+*** ERROR[1389] Object EVENT_LOG_READER does not exist in Trafodion.
+
+*** ERROR[4450] Function NOSUCHSCHEMA.EVENT_LOG_READER is not a built-in 
function or registered user-defined function.
+
+*** ERROR[8822] The statement was not prepared.
+
+>>-- Schema/UDF does not exist
 >>
 >>-- some simple tests for the timeseries builtin UDF
 >>
@@ -6759,7 +6784,10 @@ P            SLICE_TIME                  VAL1_FCI     
VAL1_LCI     VAL2_FCI
 +>              'source',
 +>              'select * from (values (''Hello'', ''World''), (''Hallo'', 
''Welt'')) T(a,b)'));
 
+*** WARNING[4323] Use of predefined UDF JDBC is deprecated and this function 
will be removed in a future release. Please use the function with the same name 
in schema TRAFODION."_LIBMGR_" instead. You may need to issue this command 
first: INITIALIZE TRAFODION, UPGRADE LIBRARY MANAGEMENT.
+
 --- SQL command prepared.
+>>-- warning 4323, predefined UDF is deprecated
 >>execute s_traf;
 
 A           B         
@@ -6770,6 +6798,27 @@ Hallo       Welt
 
 --- 2 row(s) selected.
 >>
+>>prepare s_traf from
++>select *
++>from udf("_LIBMGR_".jdbc('jdbcT4-${TRAFODION_VER}.jar',
++>                         'org.trafodion.jdbc.t4.T4Driver',
++>                         $$QUOTE$$$$JDBC_T4_URL$$$$QUOTE$$,
++>                         'any', -- no user id
++>                         'any', -- no password
++>                         'source',
++>                         'select * from (values (''Bonjour'', ''Le monde''), 
(''Hola'', ''Mundo'')) T(a,b)'));
+
+--- SQL command prepared.
+>>execute s_traf;
+
+A               B               
+--------------  ----------------
+
+Bonjour         Le monde        
+Hola            Mundo           
+
+--- 2 row(s) selected.
+>>
 >>-- negative tests
 >>
 >>select * from udf(timeseries());
@@ -6856,6 +6905,38 @@ Hallo       Welt
 
 >>-- Arguments not in pairs of column names and instructions
 >>
+>>prepare s_traf from
++>select *
++>from udf("_LIBMGR_".jdbc('trafjdbcT2-99.99.99.jar',
++>                         'org.apache.trafodion.jdbc.t2.T2Driver',
++>                         'jdbc:t2jdbc:/something',
++>                         'any', -- no user id
++>                         'any', -- no password
++>                         'source',
++>                         'some sql'));
+
+*** ERROR[11252] Exception during connect: This UDF does not support the 
Trafodion T2 driver class org.apache.trafodion.jdbc.t2.T2Driver (SQLSTATE 38020)
+
+*** ERROR[8822] The statement was not prepared.
+
+>>-- T2 driver class is not supported
+>>
+>>prepare s_traf from
++>select *
++>from udf("_LIBMGR_".jdbc('trafjdbcT2-99.99.99.jar',
++>                         'someclass',
++>                         'jdbc:t2jdbc:/something',
++>                         'any', -- no user id
++>                         'any', -- no password
++>                         'source',
++>                         'some sql'));
+
+*** ERROR[11252] Exception during connect: This UDF does not support the 
Trafodion T2 driver URL jdbc:t2jdbc:/something (SQLSTATE 38020)
+
+*** ERROR[8822] The statement was not prepared.
+
+>>-- T2 driver URL is not supported
+>>
 >>-- eclipse timeseries builtin function with a true UDF
 >>create table_mapping function timeseries(pattern char(1))
 +>returns (outval char(40))

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/regress/udr/TEST002
----------------------------------------------------------------------
diff --git a/core/sql/regress/udr/TEST002 b/core/sql/regress/udr/TEST002
index 4e21184..381d557 100644
--- a/core/sql/regress/udr/TEST002
+++ b/core/sql/regress/udr/TEST002
@@ -147,7 +147,13 @@ order by 2,1;
 
 execute s1 ;
 
--- some simple tests for the event_log_reader predefined TMUDF
+-- make sure the event_log_reader and jdbc UDFs are created (this
+-- should only be needed while we are developing Trafodion 2.3, in
+-- future releases the installer should do this automatically, by
+-- executing the upgrade command below)
+initialize trafodion, upgrade library management;
+
+-- some simple tests for the event_log_reader TMUDF
 -- (result of the UDF is not deterministic)
 select [last 0] * from udf(event_log_reader());
 select [last 0] log_ts + interval '1' day,
@@ -163,7 +169,7 @@ select [last 0] log_ts + interval '1' day,
                 log_file_name,
                 log_file_line -1,
                 case when parse_status = ' ' then 'ok' else parse_status end
-from udf(event_log_reader('f'));
+from udf("_LIBMGR_".event_log_reader('f'));
 select coalesce(min(log_file_node), 0) from udf(event_log_reader('f')) x
 where x.log_file_line <100;
 
@@ -175,11 +181,11 @@ select count(*) as num_events,
        max(log_file_line) as num_lines,
        count(distinct query_id) num_query_ids,
        sum(case when parse_status = ' ' then 0 else 1 end) num_parse_errors
-from udf(event_log_reader('f'))
+from udf("_LIBMGR_".event_log_reader('f'))
 where log_file_name = 'master_exec_regr_999_99999.log';
 -- there are 22 events in 33 lines in this file, with 13 unique query ids and 
3 parse errors
 
-select * from udf(event_log_reader('f'))
+select * from udf("_LIBMGR_".event_log_reader('f'))
 where log_file_name = 'master_exec_regr_999_99999.log'
   and (log_file_line in (1,3,8,16,23) or parse_status <> ' ')
 order by log_file_line;
@@ -190,13 +196,17 @@ sh rm $$TRAF_HOME$$/logs/master_exec_regr_999_99999.log;
 -- some negative test cases
 prepare s from select * from udf(event_log_reader(10));
 -- parameter must be a string
-prepare s from select * from udf(event_log_reader(?));
+prepare s from select * from udf("_LIBMGR_".event_log_reader(?));
 -- parameter must be available at compile time
-prepare s from select * from udf(event_log_reader(table(select * from (values 
(1)) as x)));
+prepare s from
+select *
+from udf("_LIBMGR_".event_log_reader(table(select * from (values (1)) as x)));
 -- table-valued input not allowed
 prepare s from select query_id, log_file_name, parse_status
-from udf(event_log_reader());
+from udf("_LIBMGR_".event_log_reader());
 -- log_file_name and parse_status columns not available without 'f' option
+prepare s from select * from udf(nosuchschema.event_log_reader());
+-- Schema/UDF does not exist
 
 -- some simple tests for the timeseries builtin UDF
 
@@ -248,6 +258,18 @@ from udf(jdbc('jdbcT4-${TRAFODION_VER}.jar',
               'any', -- no password
               'source',
               'select * from (values (''Hello'', ''World''), (''Hallo'', 
''Welt'')) T(a,b)'));
+-- warning 4323, predefined UDF is deprecated
+execute s_traf;
+
+prepare s_traf from
+select *
+from udf("_LIBMGR_".jdbc('jdbcT4-${TRAFODION_VER}.jar',
+                         'org.trafodion.jdbc.t4.T4Driver',
+                         $$QUOTE$$$$JDBC_T4_URL$$$$QUOTE$$,
+                         'any', -- no user id
+                         'any', -- no password
+                         'source',
+                         'select * from (values (''Bonjour'', ''Le monde''), 
(''Hola'', ''Mundo'')) T(a,b)'));
 execute s_traf;
 
 -- negative tests
@@ -306,6 +328,28 @@ from udf(timeseries(table(select * from t002_Timeseries
                     'VAL1'));
 -- Arguments not in pairs of column names and instructions
 
+prepare s_traf from
+select *
+from udf("_LIBMGR_".jdbc('trafjdbcT2-99.99.99.jar',
+                         'org.apache.trafodion.jdbc.t2.T2Driver',
+                         'jdbc:t2jdbc:/something',
+                         'any', -- no user id
+                         'any', -- no password
+                         'source',
+                         'some sql'));
+-- T2 driver class is not supported
+
+prepare s_traf from
+select *
+from udf("_LIBMGR_".jdbc('trafjdbcT2-99.99.99.jar',
+                         'someclass',
+                         'jdbc:t2jdbc:/something',
+                         'any', -- no user id
+                         'any', -- no password
+                         'source',
+                         'some sql'));
+-- T2 driver URL is not supported
+
 -- eclipse timeseries builtin function with a true UDF
 create table_mapping function timeseries(pattern char(1))
 returns (outval char(40))

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/sqlcomp/CmpSeabaseDDL.h
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/CmpSeabaseDDL.h b/core/sql/sqlcomp/CmpSeabaseDDL.h
index 1f6295d..674129e 100644
--- a/core/sql/sqlcomp/CmpSeabaseDDL.h
+++ b/core/sql/sqlcomp/CmpSeabaseDDL.h
@@ -1306,6 +1306,7 @@ protected:
   short dropSeabaseLibmgr(ExeCliInterface *inCliInterface);
   short createLibmgrProcs(ExeCliInterface * cliInterface);
   short grantLibmgrPrivs(ExeCliInterface *cliInterface);
+  short createSeabaseLibmgrCPPLib(ExeCliInterface * cliInterface);
 
   short registerNativeTable
   (

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/sqlcomp/CmpSeabaseDDLroutine.cpp
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/CmpSeabaseDDLroutine.cpp 
b/core/sql/sqlcomp/CmpSeabaseDDLroutine.cpp
index eed28cb..c1fc51d 100644
--- a/core/sql/sqlcomp/CmpSeabaseDDLroutine.cpp
+++ b/core/sql/sqlcomp/CmpSeabaseDDLroutine.cpp
@@ -1610,8 +1610,9 @@ short CmpSeabaseDDL::createSeabaseLibmgr(ExeCliInterface 
* cliInterface)
                 jarLocation.length() + 100];
 
   // Create the SEABASE_LIBMGR_SCHEMA schema
-  str_sprintf(queryBuf, "create schema if not exists %s.\"%s\" authorization 
%s ",
-              getSystemCatalog(),SEABASE_LIBMGR_SCHEMA, DB__ROOT);
+  snprintf(queryBuf, sizeof(queryBuf),
+           "create schema if not exists %s.\"%s\" authorization %s ",
+           getSystemCatalog(),SEABASE_LIBMGR_SCHEMA, DB__ROOT);
 
   cliRC = cliInterface->executeImmediate(queryBuf);
   if (cliRC < 0)
@@ -1621,9 +1622,10 @@ short CmpSeabaseDDL::createSeabaseLibmgr(ExeCliInterface 
* cliInterface)
     }
 
   // Create the SEABASE_LIBMGR_LIBRARY library
-  str_sprintf(queryBuf, "create library %s.\"%s\".%s file '%s'",
-                         getSystemCatalog(), SEABASE_LIBMGR_SCHEMA, 
SEABASE_LIBMGR_LIBRARY,
-                         jarLocation.data());
+  snprintf(queryBuf, sizeof(queryBuf),
+           "create library %s.\"%s\".%s file '%s'",
+           getSystemCatalog(), SEABASE_LIBMGR_SCHEMA, SEABASE_LIBMGR_LIBRARY,
+           jarLocation.data());
 
   cliRC = cliInterface->executeImmediate(queryBuf);
   if (cliRC < 0)
@@ -1632,6 +1634,9 @@ short CmpSeabaseDDL::createSeabaseLibmgr(ExeCliInterface 
* cliInterface)
       return -1;
     }
 
+  if (createSeabaseLibmgrCPPLib(cliInterface) < 0)
+    return -1;
+
   return (createLibmgrProcs(cliInterface));
 }
 
@@ -1647,6 +1652,7 @@ short CmpSeabaseDDL::createLibmgrProcs(ExeCliInterface * 
cliInterface)
 
       const QString * qs = NULL;
       Int32 sizeOfqs = 0;
+      const char *libName = NULL;
 
       qs = prd.newDDL;
       sizeOfqs = prd.sizeOfnewDDL;
@@ -1657,25 +1663,38 @@ short CmpSeabaseDDL::createLibmgrProcs(ExeCliInterface 
* cliInterface)
       glueQueryFragments(qryArraySize,  qs,
                          gluedQuery, gluedQuerySize);
 
+      switch (prd.whichLib)
+        {
+        case LibmgrRoutineInfo::JAVA_LIB:
+          libName = SEABASE_LIBMGR_LIBRARY;
+          break;
+        case LibmgrRoutineInfo::CPP_LIB:
+          libName = SEABASE_LIBMGR_LIBRARY_CPP;
+          break;
+        default:
+          CMPASSERT(0);
+        }
+
       param_[0] = getSystemCatalog();
       param_[1] = SEABASE_LIBMGR_SCHEMA;
       param_[2] = getSystemCatalog();
       param_[3] = SEABASE_LIBMGR_SCHEMA;
-      param_[4] = SEABASE_LIBMGR_LIBRARY;
+      param_[4] = libName;
 
       // Review comment - make sure size of queryBuf is big enough to hold
       // generated text.
       char queryBuf[strlen(getSystemCatalog())*2 + 
strlen(SEABASE_LIBMGR_SCHEMA)*2 +
                     strlen(SEABASE_LIBMGR_LIBRARY) + gluedQuerySize + 200]; 
 
-      str_sprintf(queryBuf, gluedQuery, param_[0], param_[1], param_[2], 
param_[3], param_[4]);
+      snprintf(queryBuf, sizeof(queryBuf),
+               gluedQuery, param_[0], param_[1], param_[2], param_[3], 
param_[4]);
       NADELETEBASICARRAY(gluedQuery, STMTHEAP);
 
       cliRC = cliInterface->executeImmediate(queryBuf);
       if (cliRC < 0)
         {
           cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
-        return -1;
+          return -1;
         }
     } // for
 
@@ -1690,18 +1709,36 @@ short CmpSeabaseDDL::grantLibmgrPrivs(ExeCliInterface 
*cliInterface)
 
   Lng32 cliRC = 0;
   char queryBuf[strlen(getSystemCatalog()) + strlen(SEABASE_LIBMGR_SCHEMA) +
-                strlen(SEABASE_LIBMGR_LIBRARY) + strlen(DB__LIBMGRROLE) + 200];
+                strlen(SEABASE_LIBMGR_LIBRARY) +
+                MAXOF(strlen(DB__LIBMGRROLE), strlen(PUBLIC_AUTH_NAME)) + 200];
   for (Int32 i = 0; i < 
sizeof(allLibmgrRoutineInfo)/sizeof(LibmgrRoutineInfo); i++)
     {
       // Get the next procedure routine details
       const LibmgrRoutineInfo &prd = allLibmgrRoutineInfo[i];
+      const char *grantee = NULL;
+      const char *grantOption = "";
+
+      switch (prd.whichRole)
+        {
+        case LibmgrRoutineInfo::LIBMGR_ROLE:
+          grantee = DB__LIBMGRROLE;
+          grantOption = " with grant option";
+          break;
+        case LibmgrRoutineInfo::PUBLIC:
+          grantee = PUBLIC_AUTH_NAME;
+          break;
+        default:
+          CMPASSERT(0);
+        }
 
-      str_sprintf (queryBuf, "grant execute on %s %s.\"%s\".%s to %s with 
grant option",
-                              prd.udrType,
-                              getSystemCatalog(),
-                              SEABASE_LIBMGR_SCHEMA,
-                              prd.newName,
-                              DB__LIBMGRROLE);
+      snprintf(queryBuf, sizeof(queryBuf),
+               "grant execute on %s %s.\"%s\".%s to %s%s",
+               prd.udrType,
+               getSystemCatalog(),
+               SEABASE_LIBMGR_SCHEMA,
+               prd.newName,
+               grantee,
+               grantOption);
       cliRC = cliInterface->executeImmediate(queryBuf);
       if (cliRC < 0)
         {
@@ -1731,6 +1768,9 @@ short CmpSeabaseDDL::upgradeSeabaseLibmgr(ExeCliInterface 
* cliInterface)
 
   if (cliRC == 0) // does not exist
     {
+      // give an error if the Java library does not exist, since that is
+      // an indication that we never ran
+      // INITIALIZE TRAFODION, CREATE LIBRARY MANAGEMENT
       NAString libraryName(getSystemCatalog());
       libraryName + ".\"" + SEABASE_LIBMGR_SCHEMA + "\"" + 
SEABASE_LIBMGR_LIBRARY;
       *CmpCommon::diags() << DgSqlCode(-1389)
@@ -1738,6 +1778,25 @@ short 
CmpSeabaseDDL::upgradeSeabaseLibmgr(ExeCliInterface * cliInterface)
       return -1;
     }
 
+  // now check for the C++ library, which was added in Trafodion 2.3
+  cliRC = existsInSeabaseMDTable(cliInterface,
+                                 getSystemCatalog(), SEABASE_LIBMGR_SCHEMA,
+                                 SEABASE_LIBMGR_LIBRARY_CPP,
+                                 COM_LIBRARY_OBJECT, TRUE, FALSE);
+  if (cliRC < 0)
+    return -1;
+
+  if (cliRC == 0)
+    {
+      // The Java library exists, but the C++ library does not yet
+      // exist. This means that we last created or upgraded the
+      // library management subsystem in Trafodion 2.2 or earlier.
+      // Create the C++ library, as it is needed for Trafodion 2.3
+      // and higher.
+      if (createSeabaseLibmgrCPPLib(cliInterface) < 0)
+        return -1;
+    }
+
   return (createLibmgrProcs(cliInterface));
 }
 
@@ -1773,6 +1832,31 @@ short CmpSeabaseDDL::dropSeabaseLibmgr(ExeCliInterface 
*cliInterface)
     }
   return 0;
 }
+  
+short CmpSeabaseDDL::createSeabaseLibmgrCPPLib(ExeCliInterface * cliInterface)
+{
+  Int32 cliRC = 0;
+  NAString dllLocation(getenv("TRAF_HOME"));
+  dllLocation += "/export/lib64";
+  if (strcmp(getenv("SQ_MBTYPE"), "64d") == 0)
+    dllLocation += "d";
+  // for now we use the same DLL as for the predefined UDRs
+  dllLocation += "/libudr_predef.so";
+  char queryBuf[strlen(getSystemCatalog()) + strlen(SEABASE_LIBMGR_SCHEMA) +
+                strlen(SEABASE_LIBMGR_LIBRARY_CPP) +
+                dllLocation.length() + 100];
 
+  // Create the SEABASE_LIBMGR_LIBRARY_CPP library
+  snprintf(queryBuf, sizeof(queryBuf),
+           "create library %s.\"%s\".%s file '%s'",
+           getSystemCatalog(), SEABASE_LIBMGR_SCHEMA, 
SEABASE_LIBMGR_LIBRARY_CPP,
+           dllLocation.data());
 
-  
+  cliRC = cliInterface->executeImmediate(queryBuf);
+  if (cliRC < 0)
+    {
+      cliInterface->retrieveSQLDiagnostics(CmpCommon::diags());
+      return -1;
+    }
+  return 0;
+}

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/sqlcomp/CmpSeabaseDDLroutine.h
----------------------------------------------------------------------
diff --git a/core/sql/sqlcomp/CmpSeabaseDDLroutine.h 
b/core/sql/sqlcomp/CmpSeabaseDDLroutine.h
index 76f4b65..deadac4 100644
--- a/core/sql/sqlcomp/CmpSeabaseDDLroutine.h
+++ b/core/sql/sqlcomp/CmpSeabaseDDLroutine.h
@@ -50,6 +50,8 @@
 #define SYSTEM_PROC_RM           "RM"
 #define SYSTEM_PROC_RMREX        "RMREX"
 #define SYSTEM_TMUDF_SYNCLIBUDF  "SYNCLIBUDF"
+#define SYSTEM_TMUDF_EVENT_LOG_READER "EVENT_LOG_READER"
+#define SYSTEM_TMUDF_JDBC        "JDBC"
 
 // Create procedure text for system procedures
 static const QString seabaseProcAddlibDDL[] =
@@ -244,6 +246,24 @@ static const QString seabaseProcRmrexDDL[] =
   {" ; "}
 };
 
+  static const QString seabaseTMUDFEventLogReaderDDL[] = 
+{
+  {"  CREATE TABLE_MAPPING FUNCTION IF NOT EXISTS %s.\"%s\".EVENT_LOG_READER() 
"},
+  {"  EXTERNAL NAME 'TRAF_CPP_EVENT_LOG_READER' "},
+  {"  LIBRARY %s.\"%s\".%s "},
+  {"  LANGUAGE CPP "},
+  {" ; "}
+};
+
+  static const QString seabaseTMUDFJDBCDDL[] = 
+{
+  {"  CREATE TABLE_MAPPING FUNCTION IF NOT EXISTS %s.\"%s\".JDBC() "},
+  {"  EXTERNAL NAME 'org.trafodion.libmgmt.JDBCUDR' "},
+  {"  LIBRARY %s.\"%s\".%s "},
+  {"  LANGUAGE JAVA "},
+  {" ; "}
+};
+
 struct LibmgrRoutineInfo
 {
   // type of the UDR (used in grant)
@@ -255,79 +275,131 @@ struct LibmgrRoutineInfo
   // ddl stmt corresponding to the current ddl.
   const QString *newDDL;
   Lng32 sizeOfnewDDL;
+
+  enum LibmgrLibEnum
+    {
+      JAVA_LIB,
+      CPP_LIB
+    } whichLib;
+
+  enum LibmgrRoleEnum
+    {
+      LIBMGR_ROLE,
+      PUBLIC
+    } whichRole;
 };
 
 static const LibmgrRoutineInfo allLibmgrRoutineInfo[] = {
   {"PROCEDURE",
    SYSTEM_PROC_ADDLIB, 
    seabaseProcAddlibDDL, 
-   sizeof(seabaseProcAddlibDDL)
+   sizeof(seabaseProcAddlibDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_ALTERLIB, 
    seabaseProcAlterlibDDL, 
-   sizeof(seabaseProcAlterlibDDL)
+   sizeof(seabaseProcAlterlibDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_DROPLIB, 
    seabaseProcDroplibDDL, 
-   sizeof(seabaseProcDroplibDDL)
+   sizeof(seabaseProcDroplibDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_GETFILE, 
    seabaseProcGetfileDDL, 
-   sizeof(seabaseProcGetfileDDL)
+   sizeof(seabaseProcGetfileDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_HELP, 
    seabaseProcHelpDDL, 
-   sizeof(seabaseProcHelpDDL)
+   sizeof(seabaseProcHelpDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_LS, 
    seabaseProcLsDDL, 
-   sizeof(seabaseProcLsDDL)
+   sizeof(seabaseProcLsDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_LSALL, 
    seabaseProcLsallDDL, 
-   sizeof(seabaseProcLsallDDL)
+   sizeof(seabaseProcLsallDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_PUT, 
    seabaseProcPutDDL, 
-   sizeof(seabaseProcPutDDL)
+   sizeof(seabaseProcPutDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_PUTFILE, 
    seabaseProcPutFileDDL, 
-   sizeof(seabaseProcPutFileDDL)
+   sizeof(seabaseProcPutFileDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_RM, 
    seabaseProcRmDDL, 
-   sizeof(seabaseProcRmDDL)
+   sizeof(seabaseProcRmDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"PROCEDURE",
    SYSTEM_PROC_RMREX, 
    seabaseProcRmrexDDL, 
-   sizeof(seabaseProcRmrexDDL)
+   sizeof(seabaseProcRmrexDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
   },
 
   {"FUNCTION",
    SYSTEM_TMUDF_SYNCLIBUDF,
    seabaseTMUDFSyncLibDDL,
-   sizeof(seabaseTMUDFSyncLibDDL)
+   sizeof(seabaseTMUDFSyncLibDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::LIBMGR_ROLE
+  },
+
+  {"FUNCTION",
+   SYSTEM_TMUDF_EVENT_LOG_READER,
+   seabaseTMUDFEventLogReaderDDL,
+   sizeof(seabaseTMUDFEventLogReaderDDL),
+   LibmgrRoutineInfo::CPP_LIB,
+   LibmgrRoutineInfo::PUBLIC
+  },
+
+  {"FUNCTION",
+   SYSTEM_TMUDF_JDBC,
+   seabaseTMUDFJDBCDDL,
+   sizeof(seabaseTMUDFJDBCDDL),
+   LibmgrRoutineInfo::JAVA_LIB,
+   LibmgrRoutineInfo::PUBLIC
   }
 
 };

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/src/main/java/org/trafodion/sql/udr/LmT2Driver.java
----------------------------------------------------------------------
diff --git a/core/sql/src/main/java/org/trafodion/sql/udr/LmT2Driver.java 
b/core/sql/src/main/java/org/trafodion/sql/udr/LmT2Driver.java
index 4130b09..12ccb1b 100644
--- a/core/sql/src/main/java/org/trafodion/sql/udr/LmT2Driver.java
+++ b/core/sql/src/main/java/org/trafodion/sql/udr/LmT2Driver.java
@@ -195,6 +195,18 @@ public class LmT2Driver implements java.sql.Driver
     return false;
   }
 
+  // similar to acceptsURL, but a static method that checks for substrings
+  // acceptsURL is used by the DriverManager, this static method is used
+  // internally by Trafodion (JDBC TMUDF)
+  public static boolean checkURL( String url ) 
+  {
+    for (int i = 0; i < acceptedURLs.length; i++)
+      if (url.indexOf(acceptedURLs[i]) >= 0)
+        return true;
+
+    return false;
+  }
+
   public Connection connect( String url, java.util.Properties props )
       throws SQLException
   {

http://git-wip-us.apache.org/repos/asf/trafodion/blob/562a7bdf/core/sql/src/main/java/org/trafodion/sql/udr/predef/JDBCUDR.java
----------------------------------------------------------------------
diff --git a/core/sql/src/main/java/org/trafodion/sql/udr/predef/JDBCUDR.java 
b/core/sql/src/main/java/org/trafodion/sql/udr/predef/JDBCUDR.java
index 0c6936b..f51568d 100644
--- a/core/sql/src/main/java/org/trafodion/sql/udr/predef/JDBCUDR.java
+++ b/core/sql/src/main/java/org/trafodion/sql/udr/predef/JDBCUDR.java
@@ -17,6 +17,22 @@ specific language governing permissions and limitations
 under the License.
 **********************************************************************/
 
+//*************************************************
+//
+//   ##    ##   ######   ########  ########
+//   ###   ##  ########  ########  ########
+//   ####  ##  ##    ##     ##     ##
+//   ## ## ##  ##    ##     ##     #####
+//   ##  ####  ##    ##     ##     ##
+//   ##   ###  ########     ##     ########
+//   ##    ##   ######      ##     ########
+//
+//**************************************************
+//
+// This file is deprecated. Please update file
+// core/sql/lib_mgmt/src/main/java/org/trafodion/sql/libmgmt/JDBCUDR.java
+// instead!!
+
 /***************************************************
  * A TMUDF that executes a generic JDBC query
  * and returns the result of the one SQL statement
@@ -114,6 +130,20 @@ class JDBCUDR extends UDR
               driverJarPath = 
LmUtility.getExternalLibsDirForUser(null).resolve(
                     driverJarPath);
 
+            // for security reasons we also reject the Trafodion T2
+            // driver (check both class name and URL)
+            if 
(driverClassName_.equals("org.apache.trafodion.jdbc.t2.T2Driver"))
+                throw new UDRException(
+                    38012,
+                    "This UDF does not support the Trafodion T2 driver class 
%s",
+                    driverClassName_);
+
+            if (LmT2Driver.checkURL(connectionString_))
+                throw new UDRException(
+                    38013,
+                    "This UDF does not support the Trafodion T2 driver URL %s",
+                    connectionString_);
+ 
             // Create a class loader that can access the jar file
             // specified by the caller. Note that this is only needed
             // because the JDBC UDR is a predefined UDR and is loaded
@@ -139,8 +169,9 @@ class JDBCUDR extends UDR
           catch (ClassNotFoundException cnf) {
               throw new UDRException(
                 38020,
-                "JDBC driver class %s not found. Please make sure the JDBC 
driver jar is stored in %s. Message: %s",
+                "JDBC driver class %s not found. Please make sure the JDBC 
driver jar %s is stored in %s. Message: %s",
                 driverClassName_,
+                driverJar_,
                 LmUtility.getSandboxRootForUser(null).toString(),
                 cnf.getMessage());
           }

Reply via email to