in core/src/main/java/com/jetbrains/youtrackdb/internal/core/sql/parser/SQLCreateLinkStatement.java [66:288]
private Object execute(CommandContext ctx) {
if (destField == null) {
throw new CommandExecutionException(ctx.getDatabaseSession(),
"Cannot execute the command because it has not been parsed yet");
}
final var session = ctx.getDatabaseSession();
if (session == null) {
throw new CommandSQLParsingException("",
"This command supports only the database type DatabaseDocumentTx and type '"
+ session.getClass()
+ "' was found");
}
var sourceClass =
session
.getMetadata()
.getImmutableSchemaSnapshot()
.getClass(this.sourceClass.getStringValue());
if (sourceClass == null) {
throw new CommandExecutionException(ctx.getDatabaseSession(),
"Source class '" + this.sourceClass.getStringValue() + "' not found");
}
var destClass =
session
.getMetadata()
.getImmutableSchemaSnapshot()
.getClass(this.destClass.getStringValue());
if (destClass == null) {
throw new CommandExecutionException(ctx.getDatabaseSession(),
"Destination class '" + this.destClass.getStringValue() + "' not found");
}
var cmd = "select from ";
if (destField != null && !EntityHelper.ATTRIBUTE_RID.equals(destField.value)) {
cmd = "select from " + this.destClass + " where " + destField + " = ";
}
var total = new long[1];
var linkName = name == null ? sourceField.getStringValue() : name.getStringValue();
var documentSourceClass = sourceClass;
var txCmd = cmd;
try {
final var multipleRelationship = new boolean[1];
var linkType = PropertyTypeInternal.valueOf(
type.getStringValue().toUpperCase(Locale.ENGLISH));
if (linkType != null)
// DETERMINE BASED ON FORCED TYPE
{
multipleRelationship[0] =
linkType == PropertyTypeInternal.LINKSET || linkType == PropertyTypeInternal.LINKLIST;
} else {
multipleRelationship[0] = false;
}
var txLinkType = linkType;
var txDestClass = destClass;
List<EntityImpl> result;
Object oldValue;
EntityImpl target;
// BROWSE ALL THE RECORDS OF THE SOURCE CLASS
try (var iterator = session.browseClass(documentSourceClass.getName())) {
while (iterator.hasNext() && !breakExec) {
var entity = iterator.next();
var value = entity.getProperty(sourceField.getStringValue());
if (value != null) {
if (value instanceof EntityImpl || value instanceof RID) {
// ALREADY CONVERTED
} else if (value instanceof Collection<?>) {
// TODO
} else {
// SEARCH THE DESTINATION RECORD
target = null;
if (destField != null
&& !EntityHelper.ATTRIBUTE_RID.equals(destField.value)
&& value instanceof String) {
if (((String) value).length() == 0) {
value = null;
} else {
value = "'" + value + "'";
}
}
try (var rs = session.query(txCmd + value)) {
result = toList(rs);
}
if (result == null || result.size() == 0) {
value = null;
} else if (result.size() > 1) {
throw new CommandExecutionException(ctx.getDatabaseSession(),
"Cannot create link because multiple records was found in class '"
+ txDestClass.getName()
+ "' with value "
+ value
+ " in field '"
+ destField
+ "'");
} else {
target = result.get(0);
value = target;
}
if (target != null && inverse) {
// INVERSE RELATIONSHIP
oldValue = target.getProperty(linkName);
if (oldValue != null) {
if (!multipleRelationship[0]) {
multipleRelationship[0] = true;
}
Collection<EntityImpl> coll;
if (oldValue instanceof Collection) {
// ADD IT IN THE EXISTENT COLLECTION
coll = (Collection<EntityImpl>) oldValue;
target.setDirty();
} else {
// CREATE A NEW COLLECTION FOR BOTH
coll = new ArrayList<EntityImpl>(2);
target.setProperty(linkName, coll);
coll.add((EntityImpl) oldValue);
}
coll.add(entity);
} else {
if (txLinkType != null) {
if (txLinkType == PropertyTypeInternal.LINKSET) {
value = new EntityLinkSetImpl(target);
((Set<Identifiable>) value).add(entity);
} else if (txLinkType == PropertyTypeInternal.LINKLIST) {
value = new EntityLinkListImpl(target);
((EntityLinkListImpl) value).add(entity);
} else
// IGNORE THE TYPE, SET IT AS LINK
{
value = entity;
}
} else {
value = entity;
}
target.setProperty(linkName, value);
}
} else {
// SET THE REFERENCE
entity.setProperty(linkName, value);
}
total[0]++;
}
}
}
}
if (total[0] > 0) {
if (inverse) {
// REMOVE THE OLD PROPERTY IF ANY
var prop = destClass.getProperty(linkName);
destClass = session.getMetadata().getSchema().getClass(this.destClass.getStringValue());
if (prop != null) {
if (linkType != PropertyTypeInternal.convertFromPublicType(prop.getType())) {
throw new CommandExecutionException(session,
"Cannot create the link because the property '"
+ linkName
+ "' already exists for class "
+ destClass.getName()
+ " and has a different type - actual: "
+ prop.getType()
+ " expected: "
+ linkType);
}
} else {
throw new CommandExecutionException(session,
"Cannot create the link because the property '"
+ linkName
+ "' does not exist in class '"
+ destClass.getName()
+ "'");
}
} else {
// REMOVE THE OLD PROPERTY IF ANY
var prop = sourceClass.getProperty(linkName);
sourceClass = session.getMetadata().getSchema().getClass(this.destClass.getStringValue());
if (prop != null) {
if (prop.getType() != PropertyType.LINK) {
throw new CommandExecutionException(session,
"Cannot create the link because the property '"
+ linkName
+ "' already exists for class "
+ sourceClass.getName()
+ " and has a different type - actual: "
+ prop.getType()
+ " expected: "
+ PropertyTypeInternal.LINK);
}
} else {
throw new CommandExecutionException(session,
"Cannot create the link because the property '"
+ linkName
+ "' does not exist in class '"
+ sourceClass.getName()
+ "'");
}
}
}
} catch (Exception e) {
throw BaseException.wrapException(
new CommandExecutionException(session, "Error on creation of links"), e, session);
}
return total[0];
}