UNPKG

@abaplint/runtime

Version:
316 lines • 12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.searchWithKey = searchWithKey; exports.searchWithKeyPromise = searchWithKeyPromise; exports.readTable = readTable; /* eslint-disable max-len */ const binary_search_1 = require("../binary_search"); const compare_1 = require("../compare"); const types_1 = require("../types"); /** startIndex = javascript index, return ABAP index */ function searchWithKeyEarlyExit(arr, withKey, startIndex = 0, usesTableLine, firstKeyName, firstValue) { const isStructured = arr[0] instanceof types_1.Structure; for (let index = startIndex; index < arr.length; index++) { const a = arr[index]; let row = undefined; if (usesTableLine === false && isStructured === true) { row = a.get(); } else { row = isStructured ? { table_line: a, ...a.get() } : { table_line: a }; } if (withKey(row) === true) { return { found: a, foundIndex: index + 1, }; } /* console.dir(row); console.dir(row[firstKeyName.toLowerCase()]); console.dir(firstValue); */ if ((0, compare_1.gt)(row[firstKeyName.toLowerCase()], firstValue)) { return { found: undefined, foundIndex: 0, }; } } return { found: undefined, foundIndex: 0, }; } /** startIndex = javascript index, return ABAP index */ function searchWithKey(arr, withKey, startIndex = 0, usesTableLine) { const isStructured = arr[0] instanceof types_1.Structure; for (let index = startIndex; index < arr.length; index++) { const a = arr[index]; let row = undefined; if (usesTableLine === false && isStructured === true) { row = a.get(); } else { row = isStructured ? { table_line: a, ...a.get() } : { table_line: a }; } if (withKey(row) === true) { return { found: a, foundIndex: index + 1, }; } } return { found: undefined, foundIndex: 0, }; } async function searchWithKeyPromise(arr, withKey, startIndex = 0, usesTableLine) { const isStructured = arr[0] instanceof types_1.Structure; for (let index = startIndex; index < arr.length; index++) { const a = arr[index]; let row = undefined; if (usesTableLine === false && isStructured === true) { row = a.get(); } else { row = isStructured ? { table_line: a, ...a.get() } : { table_line: a }; } if (await withKey(row) === true) { return { found: a, foundIndex: index + 1, }; } } return { found: undefined, foundIndex: 0, }; } ///////////////// function readTable(table, options) { let found = undefined; let foundIndex = 0; let binarySubrc = undefined; // console.dir(options); if (table instanceof types_1.FieldSymbol) { if (table.getPointer() === undefined) { throw new Error("GETWA_NOT_ASSIGNED"); } // return readTable(table.getPointer(), options); table = table.getPointer(); } // check if it is a primary index read specified with WITH KEY instead of WITH TABLE KEY if (options?.withTableKey === undefined && options?.withKeySimple && (table.getOptions().primaryKey?.keyFields || []).length > 0) { if (table instanceof types_1.HashedTable) { // hashed tables requires all fields for fast lookup const fields = new Set(table.getOptions().primaryKey.keyFields); for (const name in options.withKeySimple) { fields.delete(name.toUpperCase()); } if (fields.size === 0) { options.withTableKey = true; } } else { // while sorted just needs the first key field const firstKeyField = table.getOptions().primaryKey.keyFields[0]; let useKey = false; for (const name in options.withKeySimple) { if (firstKeyField === name.toUpperCase()) { useKey = true; } } if (useKey === true) { options.withTableKey = true; } } } if (options?.index) { if (table instanceof types_1.HashedTable) { throw new Error("Hashed table, READ INDEX not possible"); } const arr = table.array(); let index = options.index; if (typeof index !== "number") { if (index instanceof types_1.FieldSymbol) { if (index.getPointer() === undefined) { throw new Error("GETWA_NOT_ASSIGNED"); } index = index.getPointer(); } if (index instanceof types_1.Float || index instanceof types_1.DecFloat34) { index = index.getRaw(); } else if (index instanceof types_1.Integer8) { index = Number(index.get()); } else { index = index.get(); } } found = arr[index - 1]; if (found && options?.withKey && options?.withKey(found.get()) === false) { found = undefined; } if (found) { foundIndex = index; } } else if (table instanceof types_1.HashedTable && options?.withTableKey === true && options.withKeySimple) { const hash = table.buildHashFromSimple(options.withKeySimple); found = table.read(hash); foundIndex = 0; } else if (table instanceof types_1.HashedTable && options?.withKey) { // this is slow.. const searchResult = searchWithKey(table.array(), options.withKey, 0, options?.usesTableLine); found = searchResult.found; foundIndex = 0; } else if (options?.keyName && options.withKey && options.withKeySimple) { const arr = table.getSecondaryIndex(options.keyName); const keyInformation = table.getKeyByName(options.keyName); const firstKeyName = keyInformation?.keyFields[0]; if (firstKeyName === undefined) { throw new Error("readTable, first key name not found"); } // console.dir("SEC:"); const firstValue = options.withKeySimple[firstKeyName.toLowerCase()]; if (firstValue === undefined) { // fallback return readTable(table, { ...options, withKeySimple: undefined }); } const startIndex = (0, binary_search_1.binarySearchFrom)(arr, 0, arr.length, firstKeyName.toLowerCase(), firstValue) - 1; // console.dir("startindex: " + startIndex); if (startIndex >= 0) { const searchResult = searchWithKeyEarlyExit(arr, options.withKey, startIndex, options.usesTableLine, firstKeyName, firstValue); // console.dir(searchResult); found = searchResult.found; foundIndex = searchResult.foundIndex; } } else if ((options?.binarySearch === true || options?.withTableKey === true) && options.withKeyValue && (options?.binarySearch === true || table.getOptions().primaryKey?.type !== types_1.TableAccessType.standard) && options.withKey) { // note: it currently only uses the first key field for binary search, todo const first = options.withKeyValue[0]; const arr = table.array(); const startIndex = (0, binary_search_1.binarySearchFromRow)(arr, 0, arr.length - 1, first.key, first.value, options.usesTableLine); // todo: early exit if not found const searchResult = searchWithKey(arr, options.withKey, startIndex, options.usesTableLine); found = searchResult.found; foundIndex = searchResult.foundIndex; if (found === undefined) { if (arr.length === 0) { binarySubrc = 8; foundIndex = 1; } else { binarySubrc = 4; foundIndex = startIndex + 1; // check if going beyond the last row, todo: only checks one field const last = arr[arr.length - 1]; const isStructured = last instanceof types_1.Structure; let row = undefined; if (options.usesTableLine === false && isStructured === true) { row = last.get(); } else { row = isStructured ? { table_line: last, ...last.get() } : { table_line: last }; } if ((0, compare_1.ge)(first.value, first.key(row))) { binarySubrc = 8; } } } } else if (options?.withKey) { const arr = table.array(); const searchResult = searchWithKey(arr, options.withKey, 0, options.usesTableLine); found = searchResult.found; foundIndex = searchResult.foundIndex; } else if (options?.from) { if (options.from instanceof types_1.FieldSymbol) { options.from = options.from.getPointer(); } if (table instanceof types_1.Table && options.from instanceof types_1.Structure) { // todo: optimize if the primary key is sorted const arr = table.array(); const keys = table.getOptions()?.primaryKey?.keyFields; const isStructured = arr[0] instanceof types_1.Structure; if (keys !== undefined && isStructured === true) { // console.dir(keys); // console.dir(options.from.get()[keys[0].toLowerCase()]); for (const a of arr) { foundIndex++; let matches = true; for (const k of keys) { if ((0, compare_1.eq)(a.get()[k.toLowerCase()], options.from.get()[k.toLowerCase()]) === false) { matches = false; break; } } if (matches === true) { found = a; break; } } } } else if (table instanceof types_1.HashedTable && options.from instanceof types_1.Structure) { const key = table.buildHashFromData(options.from); found = table.read(key); } if (found === undefined) { foundIndex = 0; } if (found === undefined && table.getOptions().primaryKey?.type === types_1.TableAccessType.sorted) { binarySubrc = 8; } } else { throw new Error("runtime, readTable, unexpected input"); } let subrc = found ? 0 : 4; if (binarySubrc) { subrc = binarySubrc; } else if (subrc === 4 && (options?.binarySearch === true || options?.keyName !== undefined)) { subrc = 8; } abap.builtin.sy.get().subrc.set(subrc); abap.builtin.sy.get().tabix.set(foundIndex); if (found) { if (options.into) { if (options.into instanceof types_1.DataReference) { if (found instanceof types_1.DataReference) { options.into.assign(found.getPointer()); } else { options.into.assign(found); } } else { options.into.set(found); } } else if (options.referenceInto) { options.referenceInto.assign(found); } else if (options.assigning) { options.assigning.assign(found); } } return { subrc, foundIndex }; } //# sourceMappingURL=read_table.js.map