@@ -4,14 +4,29 @@ import { ColumnDefinition } from './ExpressionType.js';
44import { SourceTableInterface } from './SourceTableInterface.js' ;
55import { SqlTools } from './sql_filters.js' ;
66import { TablePattern } from './TablePattern.js' ;
7- import { QueryParameters , QuerySchema , SourceSchema , SourceSchemaTable , SqliteJsonRow , SqliteRow } from './types.js' ;
7+ import {
8+ EvaluationResult ,
9+ QueryParameters ,
10+ QuerySchema ,
11+ SourceSchema ,
12+ SourceSchemaTable ,
13+ SqliteJsonRow ,
14+ SqliteRow
15+ } from './types.js' ;
816import { filterJsonRow } from './utils.js' ;
17+ import { castAsText } from './sql_functions.js' ;
918
1019export interface RowValueExtractor {
1120 extract ( tables : QueryParameters , into : SqliteRow ) : void ;
1221 getTypes ( schema : QuerySchema , into : Record < string , ColumnDefinition > ) : void ;
1322}
1423
24+ export interface EvaluateRowOptions {
25+ table : SourceTableInterface ;
26+ row : SqliteRow ;
27+ bucketIds : ( params : QueryParameters ) => string [ ] ;
28+ }
29+
1530export interface BaseSqlDataQueryOptions {
1631 sourceTable : TablePattern ;
1732 table : string ;
@@ -21,7 +36,6 @@ export interface BaseSqlDataQueryOptions {
2136 descriptorName : string ;
2237 bucketParameters : string [ ] ;
2338 tools : SqlTools ;
24-
2539 errors ?: SqlRuleError [ ] ;
2640}
2741
@@ -149,6 +163,39 @@ export class BaseSqlDataQuery {
149163 return result ;
150164 }
151165
166+ evaluateRowWithOptions ( options : EvaluateRowOptions ) : EvaluationResult [ ] {
167+ try {
168+ const { table, row, bucketIds } = options ;
169+
170+ const tables = { [ this . table ] : this . addSpecialParameters ( table , row ) } ;
171+ const resolvedBucketIds = bucketIds ( tables ) ;
172+
173+ const data = this . transformRow ( tables ) ;
174+ let id = data . id ;
175+ if ( typeof id != 'string' ) {
176+ // While an explicit cast would be better, this covers against very common
177+ // issues when initially testing out sync, for example when the id column is an
178+ // auto-incrementing integer.
179+ // If there is no id column, we use a blank id. This will result in the user syncing
180+ // a single arbitrary row for this table - better than just not being able to sync
181+ // anything.
182+ id = castAsText ( id ) ?? '' ;
183+ }
184+ const outputTable = this . getOutputName ( table . name ) ;
185+
186+ return resolvedBucketIds . map ( ( bucketId ) => {
187+ return {
188+ bucket : bucketId ,
189+ table : outputTable ,
190+ id : id ,
191+ data
192+ } as EvaluationResult ;
193+ } ) ;
194+ } catch ( e ) {
195+ return [ { error : e . message ?? `Evaluating data query failed` } ] ;
196+ }
197+ }
198+
152199 protected transformRow ( tables : QueryParameters ) : SqliteJsonRow {
153200 let result : SqliteRow = { } ;
154201 for ( let extractor of this . extractors ) {
0 commit comments