File: BindCallCustomParameter.java

package info (click to toggle)
eclipselink 2.7.11-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 44,820 kB
  • sloc: java: 477,843; xml: 503; makefile: 21
file content (162 lines) | stat: -rw-r--r-- 6,729 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2019 IBM Corporation. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.databaseaccess;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.Struct;
import java.sql.Types;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.mappings.DatabaseMapping.WriteType;
import org.eclipse.persistence.mappings.structures.ObjectRelationalDatabaseField;
import org.eclipse.persistence.mappings.structures.ObjectRelationalDataTypeDescriptor;
import org.eclipse.persistence.descriptors.ClassDescriptor;

import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;

/**
 * INTERNAL:
 * <p>
 * <b>Purpose</b>: To provide a base type for customary parameters' types
 * used for binding by DatabaseCall:
 * descendants of DatabasePlatform may create instances of descendants of this class
 * in customModifyInDatabaseCall method.
 * <p>
 * <b>Responsibilities</b>:
 * <ul>
 * </ul>
 */
public class BindCallCustomParameter implements Serializable {
    /**
     * Return if unwrapped connection should be used.
     */
    public boolean shouldUseUnwrappedConnection() {
        return false;
    }

    /**
    * INTERNAL:
    * Binds the custom parameter (obj) into  the passed PreparedStatement
    * for the passed DatabaseCall.
    *
    * Called only by DatabasePlatform.setParameterValueInDatabaseCall method
    */
    public BindCallCustomParameter(Object obj) {
        this.obj = obj;
    }

    protected BindCallCustomParameter() {
    }

    /**
     * Sets this bound parameter, on the given statement, at the given parameterIndex. 
     * Note: {@link java.sql.PreparedStatement} contains setX(int parameterIndex, X x) methods. This method aligns with that pattern.
     */
    public void set(DatabasePlatform platform, PreparedStatement statement, int parameterIndex, AbstractSession session) throws SQLException {
        platform.setParameterValueInDatabaseCall(obj, statement, parameterIndex, session);
    }

    /**
     * Sets this bound parameter, on the given statement, for the given parameterName. 
     * Note: {@link java.sql.CallableStatement} contains setX(int parameterName, X x) methods. This method aligns with that pattern.
     */
    public void set(DatabasePlatform platform, CallableStatement statement, String parameterName, AbstractSession session) throws SQLException {
        platform.setParameterValueInDatabaseCall(obj, statement, parameterName, session);
    }

    public String toString() {
        if (obj != null) {
            return obj.toString();
        } else {
            return "null";
        }
    }

    protected Object obj;

    /**
     * INTERNAL:
     * Converts the parameter object from a collection or java object into a JDBC type such as an
     * Array or Struct object, based on the type information contained in the dbField object.
     * If the parameter is null, the dbField will be returned to represent the null value.
     * A Struct object
     * will be returned if:
     *  1) the dbField is an ObjectRelationalDatabaseField with its sqltype set to Types.STRUCT
     *  2) parameter is not an instanceof java.sql.Struct
     *  3) There is an ObjectRelationalDataTypeDescriptor defined for the parameter object's class
     *
     * An Array object will be returned if:
     *  1) the dbField is an ObjectRelationalDatabaseField and sqltype is set to Types.ARRAY
     *  2) parameter is an instanceof collection and is not an instanceof java.sql.Array
     *
     * This method will be used recursively on the dbField's nestedField and objects in the collection
     * to build the Array object, allowing for nested structures to be produced ie arrays of arrays
     */
    public Object convert(Object parameter, DatabaseField dbField, AbstractSession session, java.sql.Connection connection) throws SQLException{
        if (parameter == null){
            return dbField;
        }
        if (dbField == null || (!dbField.isObjectRelationalDatabaseField())){
            return parameter;
        }
        //handle STRUCT conversions
        ObjectRelationalDatabaseField ordField = ((ObjectRelationalDatabaseField)dbField);
        if (dbField.getSqlType()==Types.STRUCT){
            if (!(parameter instanceof Struct)){
                ClassDescriptor descriptor=session.getDescriptor(parameter);
                if ((descriptor!=null) && (descriptor.isObjectRelationalDataTypeDescriptor())){
                    //this is used to convert non-null objects passed through stored procedures and custom SQL to structs
                    ObjectRelationalDataTypeDescriptor ord=(ObjectRelationalDataTypeDescriptor)descriptor;
                    AbstractRecord nestedRow = ord.getObjectBuilder().buildRow(parameter, session, WriteType.UNDEFINED);
                    return ord.buildStructureFromRow(nestedRow, session, connection);
                }
            }
            return parameter;
        }
        // Handle java.sql.Array conversions from Collection or Java Arrays.
        if (parameter instanceof Object[]) {
            parameter = Arrays.asList((Object[])parameter);
        }
        if ((dbField.getSqlType()!=Types.ARRAY)||(parameter instanceof Array) || !(parameter instanceof Collection) ){
            return parameter;
        }

        Collection container = (Collection)parameter;

        DatabaseField nestedType = ordField.getNestedTypeField();

        Object[] fields = new Object[container.size()];
        int i = 0;
        for (Iterator iter = container.iterator(); iter.hasNext();) {
            Object element = iter.next();
            if (element != null) {
                element = convert(element, nestedType, session, connection);
            }
            fields[i++] = element;
        }

        return session.getPlatform().createArray(((ObjectRelationalDatabaseField)dbField).getSqlTypeName(), fields, session, connection);
    }

}