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

100% Statements 84/84
97.72% Branches 43/44
100% Functions 1/1
100% Lines 84/84

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 841x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 81x 81x 81x 81x 79x 79x 81x 81x 81x 81x 81x 2x 81x 79x 75x 75x 79x 79x 81x 21x 21x 81x 81x 81x 81x 81x 81x 81x 1x 1x 77x 77x 81x 5x 5x 3x 5x 2x 2x 5x 77x 81x 74x 1x 74x 1x 1x 1x 74x 75x 75x 81x 7x 7x 3x 7x 4x 4x 7x 75x 81x 21x 19x 19x 2x 2x 75x 75x 1x
import * as Expressions from "../../2_statements/expressions";
import {StatementNode} from "../../nodes";
import {CurrentScope} from "../_current_scope";
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, TableType, UnknownType, VoidType} from "../../types/basic";
import {StatementSyntax} from "../_statement_syntax";
import {InlineData} from "../expressions/inline_data";
import {TypeUtils} from "../_type_utils";
 
export class InsertInternal implements StatementSyntax {
  public runSyntax(node: StatementNode, scope: CurrentScope, filename: string): void {
 
    let targetType: AbstractType | undefined;
    const t = node.findDirectExpression(Expressions.Target);
    if (t) {
      targetType = new Target().runSyntax(t, scope, filename);
    }
    if (!(targetType instanceof TableType)
        && !(targetType instanceof VoidType)
        && !(targetType instanceof AnyType)
        && !(targetType instanceof UnknownType)
        && targetType !== undefined) {
      throw new Error("INSERT target must be a table");
    } 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 ? new Source().runSyntax(source, scope, filename, targetType) : targetType;
 
    if (targetType === undefined
        && !(sourceType instanceof TableType)
        && !(sourceType instanceof VoidType)
        && !(sourceType instanceof AnyType)
        && !(sourceType instanceof UnknownType)) {
      throw new Error("INSERT target must be a table");
    }
 
    const afterAssigning = node.findExpressionAfterToken("ASSIGNING");
    if (afterAssigning?.get() instanceof Expressions.FSTarget) {
      const inlinefs = afterAssigning?.findDirectExpression(Expressions.InlineFS);
      if (inlinefs) {
        new InlineFS().runSyntax(inlinefs, scope, filename, sourceType);
      } else {
        new FSTarget().runSyntax(afterAssigning, scope, filename, sourceType);
      }
    }
 
    if (node.findDirectTokenByText("INITIAL") === undefined) {
      if (new TypeUtils(scope).isAssignableStrict(sourceType, targetType) === false) {
        throw new Error("Types not compatible");
      } else if (sourceType instanceof CharacterType && targetType instanceof StringType) {
        // yea, well, INSERT doesnt convert the values automatically, like everything else?
        throw new Error("Types not compatible");
      }
    }
 
    const afterInto = node.findExpressionAfterToken("INTO");
    if (afterInto?.get() instanceof Expressions.Target && sourceType) {
      const inline = afterInto.findDirectExpression(Expressions.InlineData);
      if (inline) {
        new InlineData().runSyntax(afterInto, scope, filename, new DataReference(sourceType));
      } else {
        new Target().runSyntax(afterInto, scope, filename);
      }
    }
 
    for (const s of node.findDirectExpressions(Expressions.Source)) {
      if (s === source) {
        continue;
      }
      new Source().runSyntax(s, scope, filename, targetType);
    }
 
  }
}