All files / src/abap/5_syntax/statements insert_internal.ts

100% Statements 97/97
97.82% Branches 45/46
100% Functions 1/1
100% Lines 97/97

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 971x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 84x 84x 84x 84x 82x 82x 84x 84x 84x 84x 84x 2x 2x 2x 84x 82x 77x 77x 82x 82x 84x 21x 21x 84x 84x 84x 84x 84x 84x 84x 1x 1x 1x 1x 81x 81x 84x 5x 5x 3x 5x 2x 2x 5x 81x 84x 78x 1x 1x 1x 78x 1x 1x 1x 1x 1x 78x 79x 79x 84x 8x 8x 3x 8x 5x 5x 1x 1x 1x 1x 5x 8x 78x 84x 22x 20x 20x 2x 2x 78x 78x 1x
import * as Expressions from "../../2_statements/expressions";
import {StatementNode} from "../../nodes";
import {InlineFS} from "../expressions/inline_fs";
import {Source} from "../expressions/source";
import {Target} from "../expressions/target";
import {FSTarget} from "../expressions/fstarget";
import {AbstractType} from "../../types/basic/_abstract_type";
import {AnyType, CharacterType, DataReference, StringType, TableAccessType, TableType, UnknownType, VoidType} from "../../types/basic";
import {StatementSyntax} from "../_statement_syntax";
import {InlineData} from "../expressions/inline_data";
import {TypeUtils} from "../_type_utils";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
 
export class InsertInternal implements StatementSyntax {
  public runSyntax(node: StatementNode, input: SyntaxInput): void {
 
    let targetType: AbstractType | undefined;
    const t = node.findDirectExpression(Expressions.Target);
    if (t) {
      targetType = Target.runSyntax(t, input);
    }
    if (!(targetType instanceof TableType)
        && !(targetType instanceof VoidType)
        && !(targetType instanceof AnyType)
        && !(targetType instanceof UnknownType)
        && targetType !== undefined) {
      const message = "INSERT target must be a table";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    } else if (targetType instanceof TableType
        && node.findDirectTokenByText("LINES") === undefined) {
      targetType = targetType.getRowType();
    }
 
    let source = node.findDirectExpression(Expressions.SimpleSource4);
    if (source === undefined) {
      source = node.findDirectExpression(Expressions.Source);
    }
    const sourceType = source ? Source.runSyntax(source, input, targetType) : targetType;
 
    if (targetType === undefined
        && !(sourceType instanceof TableType)
        && !(sourceType instanceof VoidType)
        && !(sourceType instanceof AnyType)
        && !(sourceType instanceof UnknownType)) {
      const message = "INSERT target must be a table";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    }
 
    const afterAssigning = node.findExpressionAfterToken("ASSIGNING");
    if (afterAssigning?.get() instanceof Expressions.FSTarget) {
      const inlinefs = afterAssigning?.findDirectExpression(Expressions.InlineFS);
      if (inlinefs) {
        InlineFS.runSyntax(inlinefs, input, sourceType);
      } else {
        FSTarget.runSyntax(afterAssigning, input, sourceType);
      }
    }
 
    if (node.findDirectTokenByText("INITIAL") === undefined) {
      if (new TypeUtils(input.scope).isAssignableStrict(sourceType, targetType) === false) {
        const message = "Types not compatible";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      } else if (sourceType instanceof CharacterType && targetType instanceof StringType) {
        // yea, well, INSERT doesnt convert the values automatically, like everything else?
        const message = "Types not compatible";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
    }
 
    const afterInto = node.findExpressionAfterToken("INTO");
    if (afterInto?.get() instanceof Expressions.Target && sourceType) {
      const inline = afterInto.findDirectExpression(Expressions.InlineData);
      if (inline) {
        InlineData.runSyntax(afterInto, input, new DataReference(sourceType));
      } else {
        const type = Target.runSyntax(afterInto, input);
        if (type instanceof TableType && type.getAccessType() === TableAccessType.hashed) {
          const message = "Implicit or explicit index operation on hashed table is not possible";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
      }
    }
 
    for (const s of node.findDirectExpressions(Expressions.Source)) {
      if (s === source) {
        continue;
      }
      Source.runSyntax(s, input, targetType);
    }
 
  }
}