blob: 33e821639837ee6566ee7405df054f7e78adf325 [file] [log] [blame]
/*
* 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.openjpa.jdbc.meta.strats;
import java.io.InputStream;
import java.io.Reader;
import java.sql.SQLException;
import java.sql.Types;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.ValueMappingInfo;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.jdbc.sql.PostgresDictionary;
import org.apache.openjpa.jdbc.sql.Result;
import org.apache.openjpa.jdbc.sql.Row;
import org.apache.openjpa.jdbc.sql.RowManager;
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.meta.JavaTypes;
/**
* Direct mapping from a stream value to a column.
*
* @author Ignacio Andreu
* @since 1.1.0
*/
public class LobFieldStrategy extends AbstractFieldStrategy {
private static final long serialVersionUID = 1L;
private int fieldType;
private boolean isBlob;
@Override
public void map(boolean adapt) {
assertNotMappedBy();
field.mapJoin(adapt, false);
field.getKeyMapping().getValueInfo().assertNoSchemaComponents
(field.getKey(), !adapt);
field.getElementMapping().getValueInfo().assertNoSchemaComponents
(field.getElement(), !adapt);
field.setStream(true);
ValueMappingInfo vinfo = field.getValueInfo();
vinfo.assertNoJoin(field, true);
vinfo.assertNoForeignKey(field, !adapt);
DBDictionary dict = field.getMappingRepository().getDBDictionary();
DBIdentifier fieldName = DBIdentifier.newColumn(field.getName(), dict != null ? dict.delimitAll() : false);
Column tmpCol = new Column();
tmpCol.setIdentifier(fieldName);
tmpCol.setType(fieldType);
tmpCol.setJavaType(field.getTypeCode());
tmpCol.setSize(-1);
Column[] cols = vinfo.getColumns(field, fieldName,
new Column[]{ tmpCol }, field.getTable(), adapt);
field.setColumns(cols);
field.setColumnIO(vinfo.getColumnIO());
field.mapConstraints(fieldName, adapt);
field.mapPrimaryKey(adapt);
}
@Override
public Boolean isCustomInsert(OpenJPAStateManager sm, JDBCStore store) {
return null;
}
@Override
public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
Select sel = createSelect(sm, store);
store.getDBDictionary().deleteStream(store, sel);
}
@Override
public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
Object ob = toDataStoreValue(sm.fetchObjectField
(field.getIndex()), store);
Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
if (field.getColumnIO().isInsertable(0, ob == null)) {
Select sel = createSelect(sm, store);
if (isBlob) {
store.getDBDictionary().insertBlobForStreamingLoad
(row, field.getColumns()[0], store, ob, sel);
} else {
store.getDBDictionary().insertClobForStreamingLoad
(row, field.getColumns()[0], ob);
}
}
}
@Override
public void customInsert(OpenJPAStateManager sm, JDBCStore store)
throws SQLException {
Object ob = toDataStoreValue(sm.fetchObjectField
(field.getIndex()), store);
if (field.getColumnIO().isInsertable(0, ob == null)) {
if (ob != null) {
Select sel = createSelect(sm, store);
if (isBlob) {
store.getDBDictionary().updateBlob
(sel, store, (InputStream)ob);
} else {
store.getDBDictionary().updateClob
(sel, store, (Reader)ob);
}
}
}
}
@Override
public Boolean isCustomUpdate(OpenJPAStateManager sm, JDBCStore store) {
return null;
}
@Override
public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
Object ob = toDataStoreValue(sm.fetchObjectField
(field.getIndex()), store);
if (field.getColumnIO().isUpdatable(0, ob == null)) {
Row row = field.getRow(sm, store, rm, Row.ACTION_UPDATE);
Select sel = createSelect(sm, store);
if (isBlob) {
store.getDBDictionary().insertBlobForStreamingLoad
(row, field.getColumns()[0], store, ob, sel);
} else {
store.getDBDictionary().insertClobForStreamingLoad
(row, field.getColumns()[0], ob);
}
}
}
@Override
public void customUpdate(OpenJPAStateManager sm, JDBCStore store)
throws SQLException {
Object ob = toDataStoreValue(sm.fetchObjectField
(field.getIndex()), store);
if (field.getColumnIO().isUpdatable(0, ob == null)) {
if (ob != null) {
Select sel = createSelect(sm, store);
if (isBlob) {
store.getDBDictionary().updateBlob
(sel, store, (InputStream)ob);
} else {
store.getDBDictionary().updateClob
(sel, store, (Reader)ob);
}
}
}
}
@Override
public int supportsSelect(Select sel, int type, OpenJPAStateManager sm,
JDBCStore store, JDBCFetchConfiguration fetch) {
if (type == Select.TYPE_JOINLESS && sel.isSelected(field.getTable()))
return 1;
return 0;
}
@Override
public int select(Select sel, OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, int eagerMode) {
sel.select(field.getColumns()[0], field.join(sel));
return 1;
}
@Override
public void load(OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, Result res) throws SQLException {
Column col = field.getColumns()[0];
if (res.contains(col)) {
if (isBlob) {
sm.storeObject(field.getIndex(), res.getLOBStream(store, col));
} else {
sm.storeObject(field.getIndex(), res.getCharacterStream(col));
}
}
}
@Override
protected void assertNotMappedBy() {
if (field != null && field.getMappedBy() != null)
throw new UnsupportedOperationException();
}
@Override
public void setFieldMapping(FieldMapping owner) {
field = owner;
if (owner.getElementMapping().getMappingRepository().getDBDictionary()
instanceof PostgresDictionary) {
fieldType = Types.INTEGER;
isBlob = true;
field.setTypeCode(JavaTypes.INT);
} else {
if (owner.getType().isAssignableFrom(InputStream.class)) {
isBlob = true;
fieldType = Types.BLOB;
} else if (owner.getType().isAssignableFrom(Reader.class)) {
isBlob = false;
fieldType = Types.CLOB;
}
}
}
private Select createSelect(OpenJPAStateManager sm, JDBCStore store) {
Select sel = store.getSQLFactory().newSelect();
sel.select(field.getColumns()[0]);
sel.selectPrimaryKey(field.getDefiningMapping());
sel.wherePrimaryKey
(sm.getObjectId(), field.getDefiningMapping(), store);
sel.setLob(true);
return sel;
}
}