private Object execute()

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];
  }