import {FilterTable} from './filter_table' import {SortTable} from './sort_table' import {GroupTable} from './group_table' import {JoinSecondTable} from '../two/join_second_table' import { EnforceNonEmptyRecord, ValueOrNestedValueRecord, ValueRecord } from '../../record' import {Value} from '../../value' import {Subtable} from '../subtable' import { averageColumn, countRows, maximizeColumn, minimizeColumn, SelectScalar, sumColumn } from '../selection/select_scalar' import {mapTable, mapTableWithSubquery, SelectRows, selectTable} from '../selection/select_rows' import {getColumn, SelectVector} from '../selection/select_vector' import {AggregatableTable} from '../aggregatable_table' import { addAscendingOrder, addDescendingOrder, addParameterizedFilter, addParameterlessFilter, createEmptySelectStatement, joinTable, SelectStatement } from '../../statements/select_statement' import {groupTablesBy} from '../../statements/group_select_statement' import {aggregateTables, SelectGuaranteedSingleRow} from '../selection/select_guaranteed_single_row' export type ColumnType = 'string' | 'integer' | 'float' | 'boolean' export type Columns = { [P in keyof T]: ColumnType } export class Table { private readonly statement: SelectStatement constructor( public readonly tableName: string, public readonly columns: Columns) { this.statement = createEmptySelectStatement(tableName, columns) } filter(predicate: (table: T) => boolean): FilterTable filter

(provided: P, predicate: (parameters: P, table: T) => boolean): FilterTable filter

(predicateOrProvided: ((table: T) => boolean)|P, predicate?: (parameters: P, table: T) => boolean): FilterTable { return new FilterTable( typeof predicateOrProvided === 'function' ? addParameterlessFilter(this.statement, predicateOrProvided) : addParameterizedFilter(this.statement, predicate!, predicateOrProvided) ) } sortBy(sortBy: (table: T) => Value): SortTable { return new SortTable( addAscendingOrder(this.statement, sortBy) ) } sortDescendinglyBy(sortBy: (table: T) => Value): SortTable { return new SortTable( addDescendingOrder(this.statement, sortBy) ) } join(otherTable: Table, left: (firstTable: T) => K, right: (secondTable: U) => K): JoinSecondTable { return new JoinSecondTable( joinTable(this.statement, otherTable, left, right)) } select(): SelectRows { return selectTable(this.statement) } map(f: (table: T) => EnforceNonEmptyRecord & U): SelectRows map(tableInSubquery: Table, f: (s: Subtable, x: T) => EnforceNonEmptyRecord & U): SelectRows map(fOrTableInSubquery: ((table: T) => EnforceNonEmptyRecord & U)|Table, f?: (s: Subtable, x: T) => EnforceNonEmptyRecord & U): SelectRows{ return typeof fOrTableInSubquery === 'function' ? mapTable(this.statement, fOrTableInSubquery) : mapTableWithSubquery(this.statement, f!, fOrTableInSubquery) } get(f: (table: T) => U): SelectVector { return getColumn(this.statement, f) } count(): SelectScalar { return countRows(this.statement) } max(f: (table: T) => V): SelectScalar { return maximizeColumn(this.statement, f) } min(f: (table: T) => V): SelectScalar { return minimizeColumn(this.statement, f) } sum(f: (table: T) => V): SelectScalar { return sumColumn(this.statement, f) } average(f: (table: T) => V): SelectScalar { return averageColumn(this.statement, f) } aggregate( aggregation: (table: AggregatableTable, count: () => number) => EnforceNonEmptyRecord & A): SelectGuaranteedSingleRow { return aggregateTables(this.statement, aggregation) } groupBy(getKey: (table: T) => EnforceNonEmptyRecord & K): GroupTable{ return new GroupTable(groupTablesBy(this.statement, getKey)) } } export function defineTable(tableName: string, columns: Columns): Table { return new Table(tableName, columns) }