Skip to content

Commit

Permalink
betteer format postgres/cql-functions
Browse files Browse the repository at this point in the history
  • Loading branch information
patricebender committed Jan 21, 2025
1 parent e7152e1 commit cd8a731
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 12 deletions.
2 changes: 2 additions & 0 deletions hana/lib/cql-functions.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

const isTime = /^\d{1,2}:\d{1,2}:\d{1,2}$/
const isDate = /^\d{1,4}-\d{1,2}-\d{1,2}$/
const isVal = x => x && 'val' in x
Expand Down
149 changes: 144 additions & 5 deletions postgres/lib/cql-functions.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,173 @@
const session = require('./session.json')

const StandardFunctions = {
// ==============================
// Session Context Functions
// ==============================

/**
* Generates SQL statement to retrieve session context
* @param {Object} x - Object containing the session variable
* @returns {string} - SQL statement
*/
session_context: x => {
let sql = `current_setting('${session[x.val] || x.val}')`
if (x.val === '$now') sql += '::timestamp'
return sql
},

// ==============================
// String Functions
// ==============================

/**
* Generates SQL statement that checks if one string contains another
* @param {...string} args - The strings to evaluate
* @returns {string} - SQL statement
*/
contains: (...args) => `(coalesce(strpos(${args}),0) > 0)`,

/**
* Generates SQL statement for the index of the first occurrence of one string in another
* @param {string} x - The string to search
* @param {string} y - The substring to find
* @returns {string} - SQL statement
*/
indexof: (x, y) => `strpos(${x},${y}) - 1`, // strpos is 1 indexed
startswith: (x, y) => `coalesce(strpos(${x},${y}) = 1,false)`, // strpos is 1 indexed

/**
* Generates SQL statement that checks if a string starts with another string
* @param {string} x - The string to evaluate
* @param {string} y - The prefix to check
* @returns {string} - SQL statement
*/
startswith: (x, y) => `coalesce(strpos(${x},${y}) = 1,false)`,

/**
* Generates SQL statement that checks if a string ends with another string
* @param {string} x - The string to evaluate
* @param {string} y - The suffix to check
* @returns {string} - SQL statement
*/
endswith: (x, y) => `coalesce(substr(${x},length(${x}) + 1 - length(${y})) = ${y},false)`,

/**
* Generates SQL statement to match a string against a regular expression
* @param {string} x - The string to match
* @param {string} y - The regular expression
* @returns {string} - SQL statement
*/
matchesPattern: (x, y) => `regexp_like(${x}, ${y})`,

/**
* Alias for matchesPattern
* @param {string} x - The string to match
* @param {string} y - The regular expression
* @returns {string} - SQL statement
*/
matchespattern: (x, y) => `regexp_like(${x}, ${y})`,

// ==============================
// Date and Time Functions
// ==============================

/**
* Generates SQL statement for the year part of a date
* @param {string} x - The date input
* @returns {string} - SQL statement
*/
year: x => `date_part('year', ${castVal(x)})`,

/**
* Generates SQL statement for the month part of a date
* @param {string} x - The date input
* @returns {string} - SQL statement
*/
month: x => `date_part('month', ${castVal(x)})`,

/**
* Generates SQL statement for the day part of a date
* @param {string} x - The date input
* @returns {string} - SQL statement
*/
day: x => `date_part('day', ${castVal(x)})`,

/**
* Generates SQL statement to extract time from a date
* @param {string} x - The date input
* @returns {string} - SQL statement
*/
time: x => `to_char(${castVal(x)}, 'HH24:MI:SS')`,

/**
* Generates SQL statement for the hour part of a date
* @param {string} x - The date input
* @returns {string} - SQL statement
*/
hour: x => `date_part('hour', ${castVal(x)})`,

/**
* Generates SQL statement for the minute part of a date
* @param {string} x - The date input
* @returns {string} - SQL statement
*/
minute: x => `date_part('minute', ${castVal(x)})`,

/**
* Generates SQL statement for the second part of a date
* @param {string} x - The date input
* @returns {string} - SQL statement
*/
second: x => `floor(date_part('second', ${castVal(x)}))`,
fractionalseconds: x => `CAST(date_part('second', ${castVal(x)}) - floor(date_part('second', ${castVal(x)})) AS DECIMAL)`,

/**
* Generates SQL statement for fractional seconds
* @param {string} x - The date input
* @returns {string} - SQL statement
*/
fractionalseconds: x =>
`CAST(date_part('second', ${castVal(x)}) - floor(date_part('second', ${castVal(x)})) AS DECIMAL)`,
}

const isTime = /^\d{1,2}:\d{1,2}:\d{1,2}$/
const isVal = x => x && 'val' in x
const castVal = (x) => `${x}${isVal(x) ? isTime.test(x.val) ? '::TIME' : '::TIMESTAMP' : ''}`
const castVal = x => `${x}${isVal(x) ? (isTime.test(x.val) ? '::TIME' : '::TIMESTAMP') : ''}`

const HANAFunctions = {
// https://help.sap.com/docs/SAP_HANA_PLATFORM/4fe29514fd584807ac9f2a04f6754767/f12b86a6284c4aeeb449e57eb5dd3ebd.html
// ==============================
// Time Difference Functions
// ==============================

// Time functions
/**
* Generates SQL statement for the difference in 100-nanoseconds between two timestamps
* @param {string} x - Start timestamp
* @param {string} y - End timestamp
* @returns {string} - SQL statement
*/
nano100_between: (x, y) => `EXTRACT(EPOCH FROM ${y} - ${x}) * 10000000`,

/**
* Generates SQL statement for the difference in seconds between two timestamps
* @param {string} x - Start timestamp
* @param {string} y - End timestamp
* @returns {string} - SQL statement
*/
seconds_between: (x, y) => `EXTRACT(EPOCH FROM ${y} - ${x})`,

/**
* Generates SQL statement for the difference in days between two timestamps
* @param {string} x - Start timestamp
* @param {string} y - End timestamp
* @returns {string} - SQL statement
*/
days_between: (x, y) => `EXTRACT(DAY FROM ${y} - ${x})`,

/**
* Generates SQL statement for the difference in months between two timestamps
* @param {string} x - Start timestamp
* @param {string} y - End timestamp
* @returns {string} - SQL statement
*/
months_between: (x, y) => `((
(EXTRACT(YEAR FROM ${y}) - EXTRACT(YEAR FROM ${x})) * 12
)+(
Expand All @@ -47,6 +179,13 @@ const HANAFunctions = {
cast((cast( to_char(${y},'DDHH24MISSFF3') as bigint ) < cast( to_char(${x},'DDHH24MISSFF3') as bigint )) as Integer) * -1
end
))`,

/**
* Generates SQL statement for the difference in years between two timestamps
* @param {string} x - Start timestamp
* @param {string} y - End timestamp
* @returns {string} - SQL statement
*/
years_between(x, y) {
return `TRUNC(${this.months_between(x, y)} / 12,0)`
},
Expand Down
12 changes: 5 additions & 7 deletions sqlite/lib/cql-functions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict'

const StandardFunctions = {

// ==============================
// Date and Time Functions
// ==============================
Expand Down Expand Up @@ -81,10 +80,9 @@ const StandardFunctions = {
* @returns {string} - SQL statement
*/
matchespattern: (x, y) => `(${x} regexp ${y})`,
};
}

const HANAFunctions = {

// ==============================
// Timestamp Difference Functions
// ==============================
Expand Down Expand Up @@ -153,10 +151,10 @@ const HANAFunctions = {
* @returns {string} - SQL statement
*/
years_between(x, y) {
return `floor(${this.months_between(x, y)} / 12)`;
return `floor(${this.months_between(x, y)} / 12)`
},
};
}

for (let each in HANAFunctions) HANAFunctions[each.toUpperCase()] = HANAFunctions[each];
for (let each in HANAFunctions) HANAFunctions[each.toUpperCase()] = HANAFunctions[each]

module.exports = { ...StandardFunctions, ...HANAFunctions };
module.exports = { ...StandardFunctions, ...HANAFunctions }

0 comments on commit cd8a731

Please sign in to comment.