Oracle
 sql >> Base de données >  >> RDS >> Oracle

Groovy SQL Oracle Array Function/Procedure Out Parameters Registration

Je viens de rencontrer le même problème et j'ai maintenant une solution. Fondamentalement, il y a deux problèmes. La première est qu'Oracle vous demande de lui indiquer le nom du type de tableau lorsque le paramètre de sortie est enregistré. La seconde est de savoir comment persuader Groovy de vous laisser faire cela. Heureusement, il semble que les concepteurs de Groovy aient pensé à cela et vous permettent de sous-classer groovy.sql.Sql pour vous connecter au paramétrage.

J'utiliserai l'exemple de type et de procédure stockée dans cette réponse à une question similaire au niveau JDBC :

SQL> CREATE TYPE t_type AS OBJECT (val VARCHAR(4));
2  /
Type created

SQL> CREATE TYPE t_table AS TABLE OF t_type;
2  /
Type created

SQL> CREATE OR REPLACE PROCEDURE p_sql_type (p_out OUT t_table) IS
2  BEGIN
3     p_out := t_table(t_type('a'), t_type('b'));
4  END;
5  /
Procedure created

Nous avons maintenant besoin de quelques nouvelles classes Groovy :

import groovy.sql.*
import java.sql.CallableStatement
import java.sql.PreparedStatement
import java.sql.SQLException
import oracle.jdbc.driver.*

class OracleArrayOutParameter implements OutParameter {
    String typeName

    int getType() {
        OracleTypes.ARRAY
    }
}

class OracleArrayAwareSql extends Sql {

    OracleArrayAwareSql(Sql parent) {
        super(parent)
    }

    void setObject(PreparedStatement statement, int i, Object value) throws SQLException {
        if (value instanceof OracleArrayOutParameter) {
            try {
                OracleArrayOutParameter out = (OracleArrayOutParameter) value;
                ((CallableStatement) statement).registerOutParameter(i, out.getType(), out.typeName);
            } catch (ClassCastException e) {
                throw new SQLException("Cannot register out parameter.");
            }
        }
        else {
            super.setObject(statement, i, value)
        }
    }
}

L'utilisation de ceux-ci est assez simple. Vous aurez probablement besoin de la documentation Oracle sur les tableaux pour comprendre les structures de données résultantes.

// First create a "normal" groovysqlSql instance, using whatever method you like

def parent = Sql.newInstance("jdbc:oracle:thin:@host:port:sid", "user", "password", "oracle.jdbc.OracleDriver")

// Then create an OracleArrayAwareSql instance giving that parent instance as a parameter

def sql = new OracleArrayAwareSql(parent)

// Now define an OracleArrayOutParameter naming the array type

def tTableParam = new OracleArrayOutParameter(typeName: 'T_TABLE')

// And make a stored procedure call as usual

sql.call("{call p_sql_type(${tTableParam})}") { out ->

    // The returned parameter is of type oracle.sql.ARRAY

    out.array.each { struct ->
        println struct.attributes
    }
}