-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: export queryFieldInfo and jsType #625
Changes from all commits
02d64ee
03e71a7
dc6efa5
7147772
a3e47c2
3e0647a
ef45fcc
1bbfb88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,7 +27,7 @@ export function coordinator(instance) { | |
} | ||
|
||
/** | ||
* @typedef {import('@uwdata/mosaic-sql').Query | string} QueryType | ||
* @typedef {import('@uwdata/mosaic-sql').Query | import('@uwdata/mosaic-sql').DescribeQuery | string} QueryType | ||
*/ | ||
|
||
/** | ||
|
@@ -134,7 +134,8 @@ export class Coordinator { | |
* or a SQL string. | ||
* @param {object} [options] An options object. | ||
* @param {'arrow' | 'json'} [options.type] The query result format type. | ||
* @param {boolean} [options.cache=true] If true, cache the query result. | ||
* @param {boolean} [options.cache=true] If true, cache the query result in the client (QueryManager). | ||
* @param {boolean} [options.persist=false] If true, persist cached query result in the server. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you say more about where the error was coming from? I believe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The type error was from
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I now see what you mean. Updated the code. |
||
* @param {number} [options.priority] The query priority, defaults to | ||
* `Priority.Normal`. | ||
* @returns {QueryResult} A query result promise. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,25 @@ export const Distinct = 'distinct'; | |
export const Stats = { Count, Nulls, Max, Min, Distinct }; | ||
|
||
/** | ||
* @type {Record<string, (column: string) => AggregateNode>} | ||
* @typedef {Count | Distinct | Max | Min | Nulls} Stat | ||
* | ||
* @typedef {{ | ||
* table: string | import('@uwdata/mosaic-sql').TableRefNode, | ||
* column: (string | import('@uwdata/mosaic-sql').ColumnRefNode) & { aggregate?: boolean }, | ||
* stats?: Stat[] | Set<Stat> | ||
* }} FieldInfoRequest | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure |
||
* | ||
* @typedef {{ | ||
* table: FieldInfoRequest["table"], | ||
* column: string, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While |
||
* sqlType: string, | ||
* type: ReturnType<typeof jsType>, | ||
* nullable: boolean, | ||
* } & Partial<Record<Stat, number>>} FieldInfo | ||
*/ | ||
|
||
/** | ||
* @type {Record<Stat, (column: FieldInfoRequest["column"]) => AggregateNode>} | ||
*/ | ||
const statMap = { | ||
[Count]: count, | ||
|
@@ -20,18 +38,26 @@ const statMap = { | |
}; | ||
|
||
/** | ||
* | ||
* @param {string} table | ||
* @param {string} column | ||
* @param {string[]|Set<string>} stats | ||
* @returns | ||
* Get summary stats of the given column | ||
* @param {FieldInfoRequest} field | ||
* @returns {import('@uwdata/mosaic-sql').Query} | ||
*/ | ||
function summarize(table, column, stats) { | ||
function summarize({ table, column, stats }) { | ||
return Query | ||
.from(table) | ||
.select(Array.from(stats, s => ({[s]: statMap[s](column)}))); | ||
.select(Array.from(stats, s => ({ [s]: statMap[s](column) }))); | ||
} | ||
|
||
/** | ||
* Queries information about fields of a table. | ||
* If the `fields` array contains a single field with the column set to '*', | ||
* the function will retrieve and return the table information using `getTableInfo`. | ||
* Otherwise, it will query individual field information using `getFieldInfo` | ||
* for each field in the `fields` array. | ||
* @param {import('../Coordinator.js').Coordinator} mc A Mosaic coordinator. | ||
* @param {FieldInfoRequest[]} fields | ||
* @returns {Promise<FieldInfo[]>} | ||
*/ | ||
export async function queryFieldInfo(mc, fields) { | ||
if (fields.length === 1 && fields[0].column === '*') { | ||
return getTableInfo(mc, fields[0].table); | ||
|
@@ -42,13 +68,20 @@ export async function queryFieldInfo(mc, fields) { | |
} | ||
} | ||
|
||
/** | ||
* Get information about a single field of a table. | ||
* @param {import('../Coordinator.js').Coordinator} mc A Mosaic coordinator. | ||
* @param {FieldInfoRequest} field | ||
* @returns {Promise<FieldInfo>} | ||
*/ | ||
async function getFieldInfo(mc, { table, column, stats }) { | ||
// generate and issue a query for field metadata info | ||
// use GROUP BY ALL to differentiate & consolidate aggregates | ||
const q = Query | ||
.from({ source: table }) | ||
.select({ column }) | ||
.groupby(column.aggregate ? sql`ALL` : []); | ||
/** @type {{ column_name: string, column_type: string, null: "YES" | "NO" }[]} */ | ||
const [desc] = Array.from(await mc.query(Query.describe(q))); | ||
const info = { | ||
table, | ||
|
@@ -59,21 +92,28 @@ async function getFieldInfo(mc, { table, column, stats }) { | |
}; | ||
|
||
// no need for summary statistics | ||
if (!(stats?.length || stats?.size)) return info; | ||
if (!((stats instanceof Set && stats.size) || (Array.isArray(stats) && stats.length))) return info; | ||
|
||
// query for summary stats | ||
const [result] = await mc.query( | ||
summarize(table, column, stats), | ||
summarize({ table, column, stats }), | ||
{ persist: true } | ||
); | ||
|
||
// extract summary stats, copy to field info, and return | ||
return Object.assign(info, result); | ||
} | ||
|
||
/** | ||
* Get information about the fields of a table. | ||
* @param {import('../Coordinator.js').Coordinator} mc A Mosaic coordinator. | ||
* @param {FieldInfoRequest["table"]} table the table name or reference | ||
* @returns {Promise<FieldInfo[]>} | ||
*/ | ||
async function getTableInfo(mc, table) { | ||
const result = await mc.query(`DESCRIBE ${asTableRef(table)}`); | ||
return Array.from(result).map(desc => ({ | ||
/** @type {{ column_name: string, column_type: string, null: "YES" | "NO" }[]} */ | ||
const result = Array.from(await mc.query(`DESCRIBE ${asTableRef(table)}`)); | ||
return result.map(desc => ({ | ||
table, | ||
column: desc.column_name, | ||
sqlType: desc.column_type, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DescribeQuery
was missing as aQueryType
causing an error