Skip to content

Commit 23d2bac

Browse files
committed
refactor: move searchSysCache1 to Variable
This is general function that must use same checks as other memory allocation or sys/cat cache functions.
1 parent 8b3d0fe commit 23d2bac

File tree

2 files changed

+71
-34
lines changed

2 files changed

+71
-34
lines changed

src/error.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,13 @@ export class WorkspaceNotOpenedError extends PghhError {
2222
super('No workspace opened');
2323
}
2424
}
25+
26+
/**
27+
* Error occurring when argument passed to function is invalid or does
28+
* not satisfy some conditions.
29+
*/
30+
export class ArgumentInvalidError extends PghhError {
31+
constructor(actual: unknown, expected: unknown) {
32+
super(`Given argument ${actual} is invalid, expected ${expected}`);
33+
}
34+
}

src/variables.ts

Lines changed: 61 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as constants from './constants';
44
import * as dbg from './debugger';
55
import { EvaluationError, DebuggerNotAvailableError } from './debugger';
66
import { Log as logger } from './logger';
7-
import { PghhError,
7+
import { ArgumentInvalidError, PghhError,
88
unnullify } from './error';
99
import { Configuration,
1010
getWorkspaceFolder,
@@ -1601,6 +1601,46 @@ export abstract class Variable {
16011601
return await this.legacyOidOutputFunctionCall(funcOid, datum);
16021602
}
16031603

1604+
/**
1605+
* Invoke SearchSysCache1 with fallback to legacy implementation
1606+
*
1607+
* Unlike other implementations this accepts only 1 key, because for now
1608+
* we do not need other count.
1609+
*/
1610+
async searchSysCache1(cacheId: string, key: number) {
1611+
await this.checkCanUseSysCache();
1612+
1613+
if (!oidIsValid(key)) {
1614+
throw new ArgumentInvalidError(key, 'valid Oid is a positive integer');
1615+
}
1616+
1617+
const typeoid = this.debug.formatEnumValue('SysCacheIdentifier', cacheId);
1618+
1619+
if (this.context.hasSearchSysCacheFunction) {
1620+
try {
1621+
const expr = `SearchSysCache1(${typeoid}, (Datum)${key})`;
1622+
const result = await this.evaluateSysCache(expr);
1623+
if (this.debug.isNull(result)) {
1624+
return;
1625+
}
1626+
return result.memoryReference;
1627+
} catch (err) {
1628+
if (!isEvaluationError(err)) {
1629+
throw err;
1630+
}
1631+
}
1632+
1633+
this.context.hasSearchSysCacheFunction = false;
1634+
}
1635+
1636+
const expr = `SearchSysCache(${typeoid}, (Datum)${key}, 0, 0, 0)`;
1637+
const result = await this.evaluateSysCache(expr);
1638+
if (this.debug.isNull(result)) {
1639+
return;
1640+
}
1641+
return result.memoryReference;
1642+
}
1643+
16041644
private haveSysCatCacheBreakpoint() {
16051645
return !!vscode.debug.breakpoints.find(b => {
16061646
if (!b.enabled) {
@@ -1623,14 +1663,19 @@ export abstract class Variable {
16231663
??= !this.haveSysCatCacheBreakpoint();
16241664
}
16251665

1626-
/*
1627-
* Call evaluate with safety checks for sys/cat cache usage.
1628-
*/
1629-
async evaluateSysCache(expr: string) {
1666+
private async checkCanUseSysCache() {
16301667
if (!this.isSafeToUseSysCache()) {
16311668
throw new EvaluationError('Not safe to use SysCache');
16321669
}
16331670

1671+
await this.checkCanAlloc();
1672+
}
1673+
1674+
/*
1675+
* Call evaluate with safety checks for sys/cat cache usage.
1676+
*/
1677+
async evaluateSysCache(expr: string) {
1678+
await this.checkCanUseSysCache();
16341679
return await this.evaluate(expr);
16351680
}
16361681

@@ -2167,7 +2212,17 @@ export class RealVariable extends Variable {
21672212
* years (and I do not think will be changed in near future).
21682213
*/
21692214
const InvalidOid = 0;
2170-
const oidIsValid = (oid: number) => Number.isInteger(oid) && oid !== InvalidOid;
2215+
2216+
/*
2217+
* This check is not the same as in vanilla code. Specifically there is check
2218+
* that given number is Integer (JS type) and check that Oid is positive.
2219+
*
2220+
* The last check was not in original OidIsValid macro, but Oid defined as unsigned,
2221+
* so any negative number will be invalid and even if some debugger will perform
2222+
* casting for us (and in the end complete successfully) we should treat it as
2223+
* an error in OUR code.
2224+
*/
2225+
const oidIsValid = (oid: number) => Number.isInteger(oid) && oid > InvalidOid;
21712226

21722227
const InvalidAttrNumber = 0;
21732228

@@ -5769,34 +5824,6 @@ class TupleTableSlotAttributesVariable extends Variable {
57695824
const form = await this.evaluate(expr);
57705825
return form.memoryReference;
57715826
}
5772-
5773-
async searchSysCache1(cacheId: string, key: number) {
5774-
const typeoid = this.debug.formatEnumValue('SysCacheIdentifier', cacheId);
5775-
5776-
if (this.context.hasSearchSysCacheFunction) {
5777-
try {
5778-
const expr = `SearchSysCache1(${typeoid}, (Datum)${key})`;
5779-
const result = await this.evaluateSysCache(expr);
5780-
if (this.debug.isNull(result)) {
5781-
return;
5782-
}
5783-
return result.memoryReference;
5784-
} catch (err) {
5785-
if (!isEvaluationError(err)) {
5786-
throw err;
5787-
}
5788-
}
5789-
5790-
this.context.hasSearchSysCacheFunction = false;
5791-
}
5792-
5793-
const expr = `SearchSysCache(${typeoid}, (Datum)${key}, 0, 0, 0)`;
5794-
const result = await this.evaluateSysCache(expr);
5795-
if (this.debug.isNull(result)) {
5796-
return;
5797-
}
5798-
return result.memoryReference;
5799-
}
58005827

58015828
/*
58025829
* Search output function information for given type.

0 commit comments

Comments
 (0)