Skip to content

Commit

Permalink
Refactorings....
Browse files Browse the repository at this point in the history
  • Loading branch information
demmings committed Jul 6, 2024
1 parent a6a5928 commit 22a36a7
Show file tree
Hide file tree
Showing 10 changed files with 5,069 additions and 4,689 deletions.
8,878 changes: 4,511 additions & 4,367 deletions coverage/tests.lcov

Large diffs are not rendered by default.

430 changes: 272 additions & 158 deletions dist/gssql.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@demmings/gssql",
"version": "1.3.42",
"version": "1.3.43",
"description": "Google Sheets QUERY function replacement using real SQL select syntax.",
"main": "testGsSql.js",
"files": ["./src", "src", "img", "dist"],
Expand Down
30 changes: 9 additions & 21 deletions src/JoinTables.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,7 @@ class JoinTables { // skipcq: JS-0128
const result = [];

for (let i = 0; i < recIds[0].length; i++) {
const temp = [];

for (const rec of recIds) {
temp.push(typeof rec[i] === 'undefined' ? [] : rec[i]);
}
const temp = recIds.map(rec => typeof rec[i] === 'undefined' ? [] : rec[i]);
const row = temp.reduce((accumulator, currentRecords) => accumulator.filter(c => currentRecords.includes(c)), temp[0]);

if (row.length > 0) {
Expand Down Expand Up @@ -328,92 +324,89 @@ class JoinTablesRecordIds {
}

/**
*
* @param {Object} conditionAst The condition to JOIN our two tables.
* @returns {MatchingJoinRecordIDs}
*/
getRecordIDs(conditionAst) {
/** @type {Table} */
this.masterTable = this.dataJoin.isDerivedTable() ? this.dataJoin.getJoinedTableInfo() : this.primaryTableInfo;
this.calcSqlField = new CalculatedField(this.masterTable, this.primaryTableInfo, this.tableFields);

this.joinFields = this.getLeftRightFieldInfo(conditionAst);

return this.getMatchedRecordIds();
}

/**
*
* @param {TableFields} tableFields
* @returns {JoinTablesRecordIds}
*/
setTableFields(tableFields) {
this.tableFields = tableFields;

return this;
}

/**
*
* @param {Map<String,Table>} tableInfo - Map of table info.
* @returns {JoinTablesRecordIds}
*/
setTableInfo(tableInfo) {
this.tableInfo = tableInfo;

return this;
}

/**
*
* @param {BindData} bindVariables - Bind variable data.
* @returns {JoinTablesRecordIds}
*/
setBindVariables(bindVariables) {
this.bindVariables = bindVariables;

return this;
}

/**
*
* @param {String} name
* @returns {JoinTablesRecordIds}
*/
setRightTableName(name) {
this.rightTableName = name;

return this;
}

/**
*
* @param {String} name
* @returns {JoinTablesRecordIds}
*/
setLeftTableName(name) {
this.leftTableName = name;

return this;
}

/**
*
* @param {String} joinType
* @returns {JoinTablesRecordIds}
*/
setJoinType(joinType) {
this.joinType = joinType;

return this;
}

/**
*
* @param {Table} primaryTableInfo
* @returns {JoinTablesRecordIds}
*/
setPrimaryTableInfo(primaryTableInfo) {
this.primaryTableInfo = primaryTableInfo;

return this;
}

/**
*
* @returns {LeftRightJoinFields}
*/
getJoinFieldsInfo() {
Expand Down Expand Up @@ -525,7 +518,6 @@ class JoinTablesRecordIds {
}

/**
*
* @param {String} calcField
* @param {String[]} columns
* @returns {Object}
Expand Down Expand Up @@ -633,11 +625,7 @@ class JoinTablesRecordIds {
keyMasterJoinField = this.calcSqlField.evaluateCalculatedField(fieldInfo.column, recordNumber);
}

if (keyMasterJoinField !== null) {
keyMasterJoinField = keyMasterJoinField.toString().toUpperCase();
}

return keyMasterJoinField;
return keyMasterJoinField?.toString().toUpperCase();
}

/**
Expand Down
124 changes: 101 additions & 23 deletions src/ScriptSettings.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
/* *** DEBUG START ***
// Remove comments for testing in NODE
export { ScriptSettings };
export { ScriptSettings, PropertyData };
import { CacheFinance } from "../CacheFinance.js";
import { PropertiesService } from "../GasMocks.js";
class Logger {
static log(msg) {
console.log(msg);
}
}
// *** DEBUG END ***/

/** @classdesc
Expand Down Expand Up @@ -53,7 +61,6 @@ class ScriptSettings { // skipcq: JS-0128
}

/**
*
* @param {Object} propertyDataObject
* @param {Number} daysToHold
*/
Expand All @@ -62,32 +69,106 @@ class ScriptSettings { // skipcq: JS-0128
keys.forEach(key => this.put(key, propertyDataObject[key], daysToHold));
}

/**
* Puts list of data into cache using one API call. Data is converted to JSON before it is updated.
* @param {String[]} cacheKeys
* @param {any[]} newCacheData
* @param {Number} daysToHold
*/
static putAllKeysWithData(cacheKeys, newCacheData, daysToHold = 7) {
const bulkData = {};

for (let i = 0; i < cacheKeys.length; i++) {
// Create our object with an expiry time.
const objData = new PropertyData(newCacheData[i], daysToHold);

// Our property needs to be a string
bulkData[cacheKeys[i]] = JSON.stringify(objData);
}

PropertiesService.getScriptProperties().setProperties(bulkData);
}

/**
* Returns ALL cached data for each key value requested.
* Only 1 API call is made, so much faster than retrieving single values.
* @param {String[]} cacheKeys
* @returns {any[]}
*/
static getAll(cacheKeys) {
const values = [];

if (cacheKeys.length === 0) {
return values;
}

const allProperties = PropertiesService.getScriptProperties().getProperties();

// Removing properties is very slow, so remove only 1 at a time. This is enough as this function is called frequently.
ScriptSettings.expire(false, 1, allProperties);

for (const key of cacheKeys) {
const myData = allProperties[key];

if (typeof myData === 'undefined') {
values.push(null);
}
else {
/** @type {PropertyData} */
const myPropertyData = JSON.parse(myData);

if (PropertyData.isExpired(myPropertyData)) {
values.push(null);
PropertiesService.getScriptProperties().deleteProperty(key);
Logger.log(`Delete expired Script Property Key=${key}`);
}
else {
values.push(PropertyData.getData(myPropertyData));
}
}
}

return values;
}

/**
* Removes script settings that have expired.
* @param {Boolean} deleteAll - true - removes ALL script settings regardless of expiry time.
* @param {Number} maxDelete - maximum number of items to delete that are expired.
* @param {Object} allPropertiesObject - All properties already loaded. If null, will load iteself.
*/
expire(deleteAll) {
const allKeys = this.scriptProperties.getKeys();
static expire(deleteAll, maxDelete = 999, allPropertiesObject = null) {
const allProperties = allPropertiesObject === null ? PropertiesService.getScriptProperties().getProperties() : allPropertiesObject;
const allKeys = Object.keys(allProperties);
let deleteCount = 0;

for (const key of allKeys) {
const myData = this.scriptProperties.getProperty(key);
let propertyValue = null;
try {
propertyValue = JSON.parse(allProperties[key]);
}
catch (e) {
// A property that is NOT cached by CACHEFINANCE
continue;
}

if (myData !== null) {
let propertyValue = null;
try {
propertyValue = JSON.parse(myData);
}
catch (e) {
Logger.log(`Script property data is not JSON. key=${key}`);
continue;
}
const propertyOfThisApplication = propertyValue?.expiry !== undefined;

const propertyOfThisApplication = propertyValue?.expiry !== undefined;
if (propertyOfThisApplication && (PropertyData.isExpired(propertyValue) || deleteAll)) {
PropertiesService.getScriptProperties().deleteProperty(key);
delete allProperties[key];

if (propertyOfThisApplication && (PropertyData.isExpired(propertyValue) || deleteAll)) {
this.scriptProperties.deleteProperty(key);
Logger.log(`Removing expired SCRIPT PROPERTY: key=${key}`);
}
// There is no way to iterate existing from 'short' cache, so we assume there is a
// matching short cache entry and attempt to delete.
CacheFinance.deleteFromShortCache(key);

Logger.log(`Removing expired SCRIPT PROPERTY: key=${key}`);

deleteCount++;
}

if (deleteCount >= maxDelete) {
return;
}
}
}
Expand Down Expand Up @@ -122,16 +203,13 @@ class PropertyData {
}

/**
*
* @param {PropertyData} obj
* @returns {any}
*/
static getData(obj) {
let value = null;
try {
if (!PropertyData.isExpired(obj)) {
value = JSON.parse(obj.myData);
}
value = JSON.parse(obj.myData);
}
catch (ex) {
Logger.log(`Invalid property value. Not JSON: ${ex.toString()}`);
Expand Down
Loading

0 comments on commit 22a36a7

Please sign in to comment.