/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.ais.protobuf;
import com.foundationdb.ais.model.*;
import com.foundationdb.ais.util.TableChange;
import com.foundationdb.server.error.ProtobufWriteException;
import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
public class ProtobufWriter {
public static interface WriteSelector {
Columnar getSelected(Columnar columnar);
/** Called for any table.getGroup() when getSelected(table) is not null */
boolean isSelected(Group group);
/** Called for all parent joins where getSelected(Table) is not null **/
boolean isSelected(Join parentJoin);
/** Called for all GroupIndexes and all table indexes where getSelected(Table) is not null **/
boolean isSelected(Index index);
boolean isSelected(Sequence sequence);
boolean isSelected(Routine routine);
boolean isSelected(SQLJJar sqljJar);
boolean isSelected(ForeignKey foreignKey);
}
public static final WriteSelector ALL_SELECTOR = new WriteSelector() {
@Override
public Columnar getSelected(Columnar columnar) {
return columnar;
}
@Override
public boolean isSelected(Group group) {
return true;
}
@Override
public boolean isSelected(Join join) {
return true;
}
@Override
public boolean isSelected(Index index) {
return true;
}
@Override
public boolean isSelected(Sequence sequence) {
return true;
}
@Override
public boolean isSelected(Routine routine) {
return true;
}
@Override
public boolean isSelected(SQLJJar sqljJar) {
return true;
}
@Override
public boolean isSelected(ForeignKey foreignKey) {
return true;
}
};
public static abstract class TableFilterSelector implements WriteSelector {
@Override
public boolean isSelected(Index index) {
return true;
}
@Override
public boolean isSelected(Group group) {
return true;
}
@Override
public boolean isSelected(Join join) {
return true;
}
@Override
public boolean isSelected(Sequence sequence) {
return true;
}
@Override
public boolean isSelected(Routine routine) {
return true;
}
@Override
public boolean isSelected(SQLJJar sqljJar) {
return true;
}
@Override
public boolean isSelected(ForeignKey foreignKey) {
return true;
}
}
public static abstract class TableSelector extends TableFilterSelector {
public abstract boolean isSelected(Columnar columnar);
@Override
public Columnar getSelected(Columnar columnar) {
return isSelected(columnar) ? columnar : null;
}
}
public static class SingleSchemaSelector implements WriteSelector {
private final String schemaName;
public SingleSchemaSelector(String schemaName) {
this.schemaName = schemaName;
}
public String getSchemaName() {
return schemaName;
}
@Override
public Columnar getSelected(Columnar columnar) {
return schemaName.equals(columnar.getName().getSchemaName()) ? columnar : null;
}
@Override
public boolean isSelected(Group group) {
return true;
}
@Override
public boolean isSelected(Join join) {
return true;
}
@Override
public boolean isSelected(Index index) {
return true;
}
@Override
public boolean isSelected(Sequence sequence) {
return schemaName.equals(sequence.getSequenceName().getSchemaName());
}
@Override
public boolean isSelected(Routine routine) {
return schemaName.equals(routine.getName().getSchemaName());
}
@Override
public boolean isSelected(SQLJJar sqljJar) {
return schemaName.equals(sqljJar.getName().getSchemaName());
}
@Override
public boolean isSelected(ForeignKey foreignKey) {
return true;
}
}
private AISProtobuf.AkibanInformationSchema pbAIS;
private final WriteSelector selector;
public ProtobufWriter() {
this(ALL_SELECTOR);
}
public ProtobufWriter(WriteSelector selector) {
this.selector = selector;
}
/** Convert the given AIS into Protobuf classes. Returned instance also available via {@link #getPBAIS()}. */
public AISProtobuf.AkibanInformationSchema save(AkibanInformationSchema ais) {
AISProtobuf.AkibanInformationSchema.Builder aisBuilder = AISProtobuf.AkibanInformationSchema.newBuilder();
if(selector instanceof SingleSchemaSelector) {
Schema schema = ais.getSchema(((SingleSchemaSelector) selector).getSchemaName());
if(schema != null) {
writeSchema(aisBuilder, schema, selector);
}
} else {
for(Schema schema : ais.getSchemas().values()) {
writeSchema(aisBuilder, schema, selector);
}
}
pbAIS = aisBuilder.build();
return pbAIS;
}
public AISProtobuf.AkibanInformationSchema getPBAIS() {
return pbAIS;
}
/** Size buffer needs for calling {@link #serialize} */
public int getBufferSize() {
assert pbAIS != null;
return pbAIS.getSerializedSize() + 4; // + int
}
/** Serialize into <code>buffer</code>. Buffer must have array and enough space, see {@link #getBufferSize}. */
public void serialize(ByteBuffer buffer) {
assert pbAIS != null;
assert buffer.hasArray() : "Array required";
String MESSAGE_NAME = AISProtobuf.AkibanInformationSchema.getDescriptor().getFullName();
int requiredSize = getBufferSize();
int serializedSize = requiredSize - 4; // Added by requiredBufferSize
int bufferSize = buffer.limit() - buffer.position();
if(bufferSize < requiredSize) {
throw new ProtobufWriteException(MESSAGE_NAME, "Required size exceeds buffer size");
}
buffer.putInt(serializedSize);
int bufferPos = buffer.position();
bufferSize = buffer.limit() - bufferPos;
CodedOutputStream codedOutput = CodedOutputStream.newInstance(buffer.array(), bufferPos, bufferSize);
try {
pbAIS.writeTo(codedOutput);
// Successfully written, update backing buffer info
buffer.position(bufferPos + serializedSize);
} catch(IOException e) {
// CodedOutputStream really only throws OutOfSpace exception, but declares IOE
throw new ProtobufWriteException(MESSAGE_NAME, e.getMessage());
}
}
private static void writeSchema(AISProtobuf.AkibanInformationSchema.Builder aisBuilder, Schema schema, WriteSelector selector) {
AISProtobuf.Schema.Builder schemaBuilder = AISProtobuf.Schema.newBuilder();
schemaBuilder.setSchemaName(schema.getName());
// .setCharColl(convertCharAndCol(schema.getCharsetName(), schema.getCollationName()));
boolean isEmpty = true;
// Write groups into same schema as root table
for(Table table : schema.getTables().values()) {
table = (Table)selector.getSelected(table);
if(table != null) {
Group group = table.getGroup();
if((table.getParentJoin() == null) && (group != null) && selector.isSelected(group)) {
writeGroup(schemaBuilder, table.getGroup(), selector);
}
writeTable(schemaBuilder, table, selector);
isEmpty = false;
}
}
for(View view : schema.getViews().values()) {
view = (View)selector.getSelected(view);
if(view != null) {
writeView(schemaBuilder, view);
isEmpty = false;
}
}
for (Sequence sequence : schema.getSequences().values()) {
if (selector.isSelected (sequence)) {
writeSequence(schemaBuilder, sequence);
isEmpty = false;
}
}
for (Routine routine : schema.getRoutines().values()) {
if (selector.isSelected(routine)) {
writeRoutine(schemaBuilder, routine);
isEmpty = false;
}
}
for (SQLJJar sqljJar : schema.getSQLJJars().values()) {
if (selector.isSelected(sqljJar)) {
writeSQLJJar(schemaBuilder, sqljJar);
isEmpty = false;
}
}
if(!isEmpty) {
aisBuilder.addSchemas(schemaBuilder.build());
}
}
private static void writeGroup(AISProtobuf.Schema.Builder schemaBuilder, Group group, WriteSelector selector) {
final Table rootTable = group.getRoot();
AISProtobuf.Group.Builder groupBuilder = AISProtobuf.Group.newBuilder().
setRootTableName(rootTable.getName().getTableName());
if(group.getStorageDescription() != null) {
AISProtobuf.Storage.Builder storageBuilder = AISProtobuf.Storage.newBuilder();
group.getStorageDescription().writeProtobuf(storageBuilder);
groupBuilder.setStorage(storageBuilder.build());
}
for(Index index : group.getIndexes()) {
if(selector.isSelected(index)) {
writeGroupIndex(groupBuilder, index);
}
}
schemaBuilder.addGroups(groupBuilder.build());
}
private static void writeTable(AISProtobuf.Schema.Builder schemaBuilder, Table table, WriteSelector selector) {
AISProtobuf.Table.Builder tableBuilder = AISProtobuf.Table.newBuilder();
tableBuilder
.setTableName(table.getName().getTableName())
.setTableId(table.getTableId());
AISProtobuf.CharCollation cac = convertCharAndCol(table.getCharsetName(),
table.getCollationName());
if (cac != null) {
tableBuilder.setCharColl(cac);
}
if(table.getOrdinal() != null) {
tableBuilder.setOrdinal(table.getOrdinal());
}
AISProtobuf.UUID tableUuid = convertUUID(table.getUuid());
if (tableUuid != null) {
tableBuilder.setUuid(tableUuid);
}
if(table.hasVersion()) {
tableBuilder.setVersion(table.getVersion());
}
for(Column column : table.getColumnsIncludingInternal()) {
writeColumn(tableBuilder, column);
}
for(Index index : table.getIndexesIncludingInternal()) {
if(selector.isSelected(index)) {
writeTableIndex(tableBuilder, index);
}
}
Join join = table.getParentJoin();
if((join != null) && selector.isSelected(join)) {
final Table parent = join.getParent();
AISProtobuf.Join.Builder joinBuilder = AISProtobuf.Join.newBuilder();
TableName joinConstraintName = join.getConstraintName();
joinBuilder.setConstraintName(AISProtobuf.TableName.newBuilder().
setSchemaName(joinConstraintName.getSchemaName()).setTableName(joinConstraintName.getTableName())).
setParentTable(AISProtobuf.TableName.newBuilder().
setSchemaName(parent.getName().getSchemaName()).
setTableName(parent.getName().getTableName()).
build());
int position = 0;
for(JoinColumn joinColumn : join.getJoinColumns()) {
joinBuilder.addColumns(AISProtobuf.JoinColumn.newBuilder().
setParentColumn(joinColumn.getParent().getName()).
setChildColumn(joinColumn.getChild().getName()).
setPosition(position++).
build());
}
tableBuilder.setParentTable(joinBuilder.build());
}
if (table.getPendingOSC() != null) {
writePendingOSC(tableBuilder, table.getPendingOSC());
}
for(FullTextIndex index : table.getOwnFullTextIndexes()) {
if(selector.isSelected(index)) {
writeFullTextIndex(tableBuilder, index);
}
}
for(ForeignKey fk : table.getReferencingForeignKeys()) {
if(selector.isSelected(fk)) {
writeForeignKey(tableBuilder, fk);
}
}
schemaBuilder.addTables(tableBuilder.build());
}
private static void writeColumn(AISProtobuf.Table.Builder tableBuilder, Column column) {
tableBuilder.addColumns(writeColumnCommon(column));
}
private static void writeView(AISProtobuf.Schema.Builder schemaBuilder, View view) {
AISProtobuf.View.Builder viewBuilder = AISProtobuf.View.newBuilder();
viewBuilder.
setViewName(view.getName().getTableName()).
setDefinition(view.getDefinition());
// Not yet in AIS: description, protected
for(Column column : view.getColumnsIncludingInternal()) {
writeColumn(viewBuilder, column);
}
for(String key : view.getDefinitionProperties().stringPropertyNames()) {
String value = view.getDefinitionProperties().getProperty(key);
viewBuilder.addDefinitionProperties(AISProtobuf.Property.newBuilder().
setKey(key).setValue(value).
build());
}
for(Map.Entry<TableName,Collection<String>> entry : view.getTableColumnReferences().entrySet()) {
AISProtobuf.ColumnReference.Builder referenceBuilder =
AISProtobuf.ColumnReference.newBuilder().
setTable(AISProtobuf.TableName.newBuilder().
setSchemaName(entry.getKey().getSchemaName()).
setTableName(entry.getKey().getTableName()).
build());
for (String column : entry.getValue()) {
referenceBuilder.addColumns(column);
}
viewBuilder.addReferences(referenceBuilder.build());
}
schemaBuilder.addViews(viewBuilder.build());
}
private static void writeColumn(AISProtobuf.View.Builder viewBuilder, Column column) {
viewBuilder.addColumns(writeColumnCommon(column));
}
private static AISProtobuf.Column writeColumnCommon(Column column) {
AISProtobuf.Column.Builder columnBuilder = AISProtobuf.Column.newBuilder().
setColumnName(column.getName()).
setTypeName(column.getTypeName()).
setTypeBundleUUID(convertUUID(column.getTypeBundleUUID())).
setTypeVersion(column.getTypeVersion()).
setIsNullable(column.getNullable()).
setPosition(column.getPosition());
if(column.hasCharsetAndCollation()) {
columnBuilder.setCharColl(convertCharAndCol(column.getCharsetName(), column.getCollationName()));
}
AISProtobuf.UUID columnUuid = convertUUID(column.getUuid());
if (columnUuid != null) {
columnBuilder.setUuid(columnUuid);
}
if(column.getTypeParameter1() != null) {
columnBuilder.setTypeParam1(column.getTypeParameter1());
}
if(column.getTypeParameter2() != null) {
columnBuilder.setTypeParam2(column.getTypeParameter2());
}
if (column.getDefaultIdentity() != null) {
columnBuilder.setDefaultIdentity (column.getDefaultIdentity());
}
if (column.getIdentityGenerator() != null) {
columnBuilder.setSequence(AISProtobuf.TableName.newBuilder()
.setSchemaName(column.getIdentityGenerator().getSequenceName().getSchemaName())
.setTableName(column.getIdentityGenerator().getSequenceName().getTableName())
.build());
}
Long maxStorage = column.getMaxStorageSizeWithoutComputing();
if(maxStorage != null) {
columnBuilder.setMaxStorageSize(maxStorage);
}
Integer prefix = column.getPrefixSizeWithoutComputing();
if(prefix != null) {
columnBuilder.setPrefixSize(prefix);
}
if(column.getDefaultValue() != null) {
columnBuilder.setDefaultValue(column.getDefaultValue());
}
if(column.getDefaultFunction() != null) {
columnBuilder.setDefaultFunction(column.getDefaultFunction());
}
return columnBuilder.build();
}
private static AISProtobuf.Index writeIndexCommon(Index index, boolean withTableName) {
final IndexName indexName = index.getIndexName();
AISProtobuf.Index.Builder indexBuilder = AISProtobuf.Index.newBuilder();
AISProtobuf.TableName.Builder tableNameBuilder = AISProtobuf.TableName.newBuilder();
AISProtobuf.TableName constraintName;
indexBuilder.
setIndexName(indexName.getName()).
setIndexId(index.getIndexId()).
setIsPK(index.isPrimaryKey()).
setIsUnique(index.isUnique()).
setIndexMethod(convertIndexMethod(index.getIndexMethod()));
if (index.getConstraintName() != null) {
tableNameBuilder.
setSchemaName(index.getConstraintName().getSchemaName()).
setTableName(index.getConstraintName().getTableName());
constraintName = tableNameBuilder.build();
indexBuilder.setConstraintName(constraintName);
}
// Not yet in AIS: description
if(index.isGroupIndex()) {
indexBuilder.setJoinType(convertJoinType(index.getJoinType()));
}
if(index.getStorageDescription() != null) {
AISProtobuf.Storage.Builder storageBuilder = AISProtobuf.Storage.newBuilder();
index.getStorageDescription().writeProtobuf(storageBuilder);
indexBuilder.setStorage(storageBuilder.build());
}
if (index.getIndexMethod() == Index.IndexMethod.GEO_LAT_LON ||
index.getIndexMethod() == Index.IndexMethod.GEO_WKB ||
index.getIndexMethod() == Index.IndexMethod.GEO_WKT) {
indexBuilder.
setFirstSpatialArg(index.firstSpatialArgument()).
setLastSpatialArg(index.lastSpatialArgument()).
setDimensions(index.dimensions());
}
for(IndexColumn indexColumn : index.getKeyColumns()) {
writeIndexColumn(indexBuilder, indexColumn, withTableName);
}
return indexBuilder.build();
}
private static void writeTableIndex(AISProtobuf.Table.Builder tableBuilder, Index index) {
tableBuilder.addIndexes(writeIndexCommon(index, false));
}
private static void writeGroupIndex(AISProtobuf.Group.Builder groupBuilder, Index index) {
groupBuilder.addIndexes(writeIndexCommon(index, true));
}
private static void writeFullTextIndex(AISProtobuf.Table.Builder tableBuilder, FullTextIndex index) {
tableBuilder.addFullTextIndexes(writeIndexCommon(index, true));
}
private static void writeIndexColumn(AISProtobuf.Index.Builder indexBuilder, IndexColumn indexColumn, boolean withTableName) {
AISProtobuf.IndexColumn.Builder indexColumnBuilder = AISProtobuf.IndexColumn.newBuilder().
setColumnName(indexColumn.getColumn().getName()).
setIsAscending(indexColumn.isAscending()).
setPosition(indexColumn.getPosition());
if(indexColumn.getIndexedLength() != null) {
indexColumnBuilder.setIndexedLength(indexColumn.getIndexedLength());
}
if(withTableName) {
TableName tableName = indexColumn.getColumn().getTable().getName();
indexColumnBuilder.setTableName(
AISProtobuf.TableName.newBuilder().
setSchemaName(tableName.getSchemaName()).
setTableName(tableName.getTableName()).
build()
);
}
indexBuilder.addColumns(indexColumnBuilder.build());
}
private static AISProtobuf.UUID convertUUID(UUID uuid) {
if (uuid == null)
return null;
return AISProtobuf.UUID.newBuilder().
setMostSignificantBits(uuid.getMostSignificantBits()).
setLeastSignificantBits(uuid.getLeastSignificantBits()).
build();
}
private static AISProtobuf.JoinType convertJoinType(Index.JoinType joinType) {
switch(joinType) {
case LEFT: return AISProtobuf.JoinType.LEFT_OUTER_JOIN;
case RIGHT: return AISProtobuf.JoinType.RIGHT_OUTER_JOIN;
}
throw new ProtobufWriteException(AISProtobuf.Join.getDescriptor().getFullName(),
"No match for Index.JoinType "+joinType.name());
}
private static AISProtobuf.CharCollation convertCharAndCol(String charset, String collation) {
if ((charset == null) && (collation == null))
return null;
return AISProtobuf.CharCollation.newBuilder().
setCharacterSetName(charset).
setCollationOrderName(collation).
build();
}
private static AISProtobuf.IndexMethod convertIndexMethod(Index.IndexMethod indexMethod) {
switch (indexMethod) {
case NORMAL:
default:
return AISProtobuf.IndexMethod.NORMAL;
case GEO_LAT_LON:
return AISProtobuf.IndexMethod.GEO_LAT_LON;
case GEO_WKB:
return AISProtobuf.IndexMethod.GEO_WKB;
case GEO_WKT:
return AISProtobuf.IndexMethod.GEO_WKT;
case FULL_TEXT:
return AISProtobuf.IndexMethod.FULL_TEXT;
}
}
private static void writePendingOSC(AISProtobuf.Table.Builder tableBuilder, PendingOSC pendingOSC) {
AISProtobuf.PendingOSC.Builder oscBuilder = AISProtobuf.PendingOSC.newBuilder();
oscBuilder.setOriginalName(pendingOSC.getOriginalName());
for (TableChange columnChange : pendingOSC.getColumnChanges()) {
oscBuilder.addColumnChanges(writePendingOSChange(columnChange));
}
for (TableChange indexChange : pendingOSC.getIndexChanges()) {
oscBuilder.addIndexChanges(writePendingOSChange(indexChange));
}
if (pendingOSC.getCurrentName() != null)
oscBuilder.setCurrentName(pendingOSC.getCurrentName());
tableBuilder.setPendingOSC(oscBuilder.build());
}
private static AISProtobuf.PendingOSChange writePendingOSChange(TableChange tableChange) {
AISProtobuf.PendingOSChange.Builder oscBuilder = AISProtobuf.PendingOSChange.newBuilder();
switch (tableChange.getChangeType()) {
case ADD:
oscBuilder.setType(AISProtobuf.PendingOSChangeType.ADD);
oscBuilder.setNewName(tableChange.getNewName());
break;
case DROP:
oscBuilder.setType(AISProtobuf.PendingOSChangeType.DROP);
oscBuilder.setOldName(tableChange.getOldName());
break;
case MODIFY:
oscBuilder.setType(AISProtobuf.PendingOSChangeType.MODIFY);
oscBuilder.setOldName(tableChange.getOldName());
oscBuilder.setNewName(tableChange.getNewName());
break;
}
return oscBuilder.build();
}
private static void writeForeignKey(AISProtobuf.Table.Builder tableBuilder, ForeignKey fk) {
AISProtobuf.ForeignKey.Builder fkBuilder = AISProtobuf.ForeignKey.newBuilder();
fkBuilder
.setConstraintName(fk.getConstraintName().getTableName())
.setReferencedTable(AISProtobuf.TableName.newBuilder().
setSchemaName(fk.getReferencedTable().getName().getSchemaName()).
setTableName(fk.getReferencedTable().getName().getTableName()).
build());
for(Column fkColumn : fk.getReferencingColumns()) {
fkBuilder.addReferencingColumns(fkColumn.getName());
}
for(Column fkColumn : fk.getReferencedColumns()) {
fkBuilder.addReferencedColumns(fkColumn.getName());
}
fkBuilder.setOnDelete(convertForeignKeyAction(fk.getDeleteAction()));
fkBuilder.setOnUpdate(convertForeignKeyAction(fk.getUpdateAction()));
fkBuilder.setDeferrable(fk.isDeferrable());
fkBuilder.setInitiallyDeferred(fk.isInitiallyDeferred());
tableBuilder.addForeignKeys(fkBuilder.build());
}
private static AISProtobuf.ForeignKeyAction convertForeignKeyAction(ForeignKey.Action action) {
switch (action) {
case NO_ACTION:
default:
return AISProtobuf.ForeignKeyAction.NO_ACTION;
case RESTRICT:
return AISProtobuf.ForeignKeyAction.RESTRICT;
case CASCADE:
return AISProtobuf.ForeignKeyAction.CASCADE;
case SET_NULL:
return AISProtobuf.ForeignKeyAction.SET_NULL;
case SET_DEFAULT:
return AISProtobuf.ForeignKeyAction.SET_DEFAULT;
}
}
private static void writeSequence (AISProtobuf.Schema.Builder schemaBuilder, Sequence sequence) {
AISProtobuf.Sequence.Builder sequenceBuilder = AISProtobuf.Sequence.newBuilder()
.setSequenceName(sequence.getSequenceName().getTableName())
.setStart(sequence.getStartsWith())
.setIncrement(sequence.getIncrement())
.setMinValue(sequence.getMinValue())
.setMaxValue(sequence.getMaxValue())
.setIsCycle(sequence.isCycle());
if(sequence.getStorageDescription() != null) {
AISProtobuf.Storage.Builder storageBuilder = AISProtobuf.Storage.newBuilder();
sequence.getStorageDescription().writeProtobuf(storageBuilder);
sequenceBuilder.setStorage(storageBuilder.build());
}
schemaBuilder.addSequences (sequenceBuilder.build());
}
private static void writeRoutine(AISProtobuf.Schema.Builder schemaBuilder, Routine routine) {
AISProtobuf.Routine.Builder routineBuilder = AISProtobuf.Routine.newBuilder()
.setRoutineName(routine.getName().getTableName())
.setLanguage(routine.getLanguage())
.setCallingConvention(convertRoutineCallingConvention(routine.getCallingConvention()));
for (Parameter parameter : routine.getParameters()) {
writeParameter(routineBuilder, parameter);
}
if (routine.getReturnValue() != null) {
writeParameter(routineBuilder, routine.getReturnValue());
}
SQLJJar sqljJar = routine.getSQLJJar();
if (sqljJar != null) {
routineBuilder.setJarName(AISProtobuf.TableName.newBuilder()
.setSchemaName(sqljJar.getName().getSchemaName())
.setTableName(sqljJar.getName().getTableName())
.build());
}
if (routine.getClassName() != null)
routineBuilder.setClassName(routine.getClassName());
if (routine.getMethodName() != null)
routineBuilder.setMethodName(routine.getMethodName());
if (routine.getDefinition() != null)
routineBuilder.setDefinition(routine.getDefinition());
if (routine.getSQLAllowed() != null)
routineBuilder.setSqlAllowed(convertRoutineSQLAllowed(routine.getSQLAllowed()));
if (routine.getDynamicResultSets() > 0)
routineBuilder.setDynamicResultSets(routine.getDynamicResultSets());
if (routine.isDeterministic())
routineBuilder.setDeterministic(routine.isDeterministic());
if (routine.isCalledOnNullInput())
routineBuilder.setCalledOnNullInput(routine.isCalledOnNullInput());
if (routine.getVersion() > 0)
routineBuilder.setVersion(routine.getVersion());
schemaBuilder.addRoutines(routineBuilder.build());
}
private static void writeParameter(AISProtobuf.Routine.Builder routineBuilder, Parameter parameter) {
AISProtobuf.Parameter.Builder parameterBuilder = AISProtobuf.Parameter.newBuilder()
.setDirection(convertParameterDirection(parameter.getDirection()))
.setTypeName(parameter.getTypeName())
.setTypeBundleUUID(convertUUID(parameter.getTypeBundleUUID()))
.setTypeVersion(parameter.getTypeVersion());
if (parameter.getTypeParameter1() != null) {
parameterBuilder.setTypeParam1(parameter.getTypeParameter1());
}
if (parameter.getTypeParameter2() != null) {
parameterBuilder.setTypeParam2(parameter.getTypeParameter2());
}
if (parameter.getName() != null) {
parameterBuilder.setParameterName(parameter.getName());
}
routineBuilder.addParameters(parameterBuilder.build());
}
private static AISProtobuf.RoutineCallingConvention convertRoutineCallingConvention(Routine.CallingConvention callingConvention) {
switch (callingConvention) {
case JAVA:
default:
return AISProtobuf.RoutineCallingConvention.JAVA;
case LOADABLE_PLAN:
return AISProtobuf.RoutineCallingConvention.LOADABLE_PLAN;
case SQL_ROW:
return AISProtobuf.RoutineCallingConvention.SQL_ROW;
case SCRIPT_FUNCTION_JAVA:
return AISProtobuf.RoutineCallingConvention.SCRIPT_FUNCTION_JAVA;
case SCRIPT_BINDINGS:
return AISProtobuf.RoutineCallingConvention.SCRIPT_BINDINGS;
case SCRIPT_FUNCTION_JSON:
return AISProtobuf.RoutineCallingConvention.SCRIPT_FUNCTION_JSON;
case SCRIPT_BINDINGS_JSON:
return AISProtobuf.RoutineCallingConvention.SCRIPT_BINDINGS_JSON;
case SCRIPT_LIBRARY:
return AISProtobuf.RoutineCallingConvention.SCRIPT_LIBRARY;
}
}
private static AISProtobuf.RoutineSQLAllowed convertRoutineSQLAllowed(Routine.SQLAllowed sqlAllowed) {
switch (sqlAllowed) {
case MODIFIES_SQL_DATA:
default:
return AISProtobuf.RoutineSQLAllowed.MODIFIES_SQL_DATA;
case READS_SQL_DATA:
return AISProtobuf.RoutineSQLAllowed.READS_SQL_DATA;
case CONTAINS_SQL:
return AISProtobuf.RoutineSQLAllowed.CONTAINS_SQL;
case NO_SQL:
return AISProtobuf.RoutineSQLAllowed.NO_SQL;
}
}
private static AISProtobuf.ParameterDirection convertParameterDirection(Parameter.Direction parameterDirection) {
switch (parameterDirection) {
case IN:
default:
return AISProtobuf.ParameterDirection.IN;
case OUT:
return AISProtobuf.ParameterDirection.OUT;
case INOUT:
return AISProtobuf.ParameterDirection.INOUT;
case RETURN:
return AISProtobuf.ParameterDirection.RETURN;
}
}
private static void writeSQLJJar(AISProtobuf.Schema.Builder schemaBuilder, SQLJJar sqljJar) {
AISProtobuf.SQLJJar.Builder jarBuilder = AISProtobuf.SQLJJar.newBuilder()
.setJarName(sqljJar.getName().getTableName())
.setUrl(sqljJar.getURL().toExternalForm());
if (sqljJar.getVersion() > 0)
jarBuilder.setVersion(sqljJar.getVersion());
schemaBuilder.addSqljJars(jarBuilder.build());
}
}