@jarenjs/json 0.46.4 → 0.49.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +1 -1
- package/README.md +47 -4
- package/dist/types/query/operators.d.ts +42 -0
- package/dist/types/query/series.d.ts +164 -0
- package/docs/QUERY-FORMAT.md +172 -4
- package/package.json +2 -2
- package/schemas/jaren-jslt.draft-07.schema.json +236 -0
- package/schemas/jaren-jslt.llm-profile.schema.json +229 -0
- package/schemas/jaren-jslt.schema.json +236 -0
- package/schemas/jaren-query.draft-07.schema.json +236 -0
- package/schemas/jaren-query.llm-profile.schema.json +229 -0
- package/schemas/jaren-query.schema.json +122 -2
- package/src/query/normalize.js +44 -1
- package/src/query/operators.js +332 -3
- package/src/query/series.js +415 -0
|
@@ -160,6 +160,15 @@
|
|
|
160
160
|
},
|
|
161
161
|
{
|
|
162
162
|
"$ref": "#/$defs/schemaOperatorPhrase"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"$ref": "#/$defs/seriesSpecPhrase"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"$ref": "#/$defs/asOfPhrase"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"$ref": "#/$defs/timeBucketPhrase"
|
|
163
172
|
}
|
|
164
173
|
]
|
|
165
174
|
},
|
|
@@ -607,6 +616,226 @@
|
|
|
607
616
|
"maxItems": 2
|
|
608
617
|
}
|
|
609
618
|
},
|
|
619
|
+
"seriesSpec": {
|
|
620
|
+
"description": "A $resample or $rolling spec (QUERY-FORMAT.md section 8.16): a VERBATIM literal, never an expression, so the width, the aggregate, the fill policy, the wall clock and the row selectors are read once when the query compiles. Closed: an unknown member is JQ0003. 'every'/'width' is an ISO 8601 duration or a count of milliseconds; 'origin'/'start'/'end' are epoch milliseconds or an RFC 3339 string; 'at'/'value' are singular paths where '$' reads as the ROW. A named 'zone' needs an injected zoneProvider - this suite bundles no time-zone database.",
|
|
621
|
+
"type": "object",
|
|
622
|
+
"properties": {
|
|
623
|
+
"every": {
|
|
624
|
+
"$ref": "#/$defs/seriesSpan"
|
|
625
|
+
},
|
|
626
|
+
"width": {
|
|
627
|
+
"$ref": "#/$defs/seriesSpan"
|
|
628
|
+
},
|
|
629
|
+
"origin": {
|
|
630
|
+
"$ref": "#/$defs/seriesInstant"
|
|
631
|
+
},
|
|
632
|
+
"start": {
|
|
633
|
+
"$ref": "#/$defs/seriesInstant"
|
|
634
|
+
},
|
|
635
|
+
"end": {
|
|
636
|
+
"$ref": "#/$defs/seriesInstant"
|
|
637
|
+
},
|
|
638
|
+
"aggregate": {
|
|
639
|
+
"enum": [
|
|
640
|
+
"sum",
|
|
641
|
+
"mean",
|
|
642
|
+
"min",
|
|
643
|
+
"max",
|
|
644
|
+
"first",
|
|
645
|
+
"last",
|
|
646
|
+
"count"
|
|
647
|
+
]
|
|
648
|
+
},
|
|
649
|
+
"fill": {
|
|
650
|
+
"enum": [
|
|
651
|
+
"omit",
|
|
652
|
+
"null",
|
|
653
|
+
"zero",
|
|
654
|
+
"locf",
|
|
655
|
+
"linear"
|
|
656
|
+
]
|
|
657
|
+
},
|
|
658
|
+
"minPeriods": {
|
|
659
|
+
"type": "integer",
|
|
660
|
+
"minimum": 1
|
|
661
|
+
},
|
|
662
|
+
"at": {
|
|
663
|
+
"$ref": "#/$defs/rowSelector"
|
|
664
|
+
},
|
|
665
|
+
"value": {
|
|
666
|
+
"$ref": "#/$defs/rowSelector"
|
|
667
|
+
},
|
|
668
|
+
"zone": {
|
|
669
|
+
"type": "string",
|
|
670
|
+
"minLength": 1
|
|
671
|
+
},
|
|
672
|
+
"offset": {
|
|
673
|
+
"type": "number"
|
|
674
|
+
},
|
|
675
|
+
"disambiguation": {
|
|
676
|
+
"enum": [
|
|
677
|
+
"reject",
|
|
678
|
+
"earlier",
|
|
679
|
+
"later"
|
|
680
|
+
]
|
|
681
|
+
}
|
|
682
|
+
},
|
|
683
|
+
"additionalProperties": false
|
|
684
|
+
},
|
|
685
|
+
"seriesSpan": {
|
|
686
|
+
"description": "A width: an ISO 8601 duration string ('PT1H', 'P1M') or a count of milliseconds. A duration mixing the calendar and clock families ('P1MT1H') is refused by the compiler.",
|
|
687
|
+
"anyOf": [
|
|
688
|
+
{
|
|
689
|
+
"type": "string",
|
|
690
|
+
"minLength": 1
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
"type": "number",
|
|
694
|
+
"exclusiveMinimum": 0
|
|
695
|
+
}
|
|
696
|
+
]
|
|
697
|
+
},
|
|
698
|
+
"seriesInstant": {
|
|
699
|
+
"description": "An instant: epoch milliseconds, or an RFC 3339 string. A full-time names no instant and is refused by the compiler.",
|
|
700
|
+
"anyOf": [
|
|
701
|
+
{
|
|
702
|
+
"type": "number"
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
"type": "string",
|
|
706
|
+
"minLength": 1
|
|
707
|
+
}
|
|
708
|
+
]
|
|
709
|
+
},
|
|
710
|
+
"rowSelector": {
|
|
711
|
+
"description": "Where a member lives in a source row: a singular JSONPath whose '$' is the ROW rather than the document ('$.on', \"$['recorded at']\", '$.meta.at'). Wildcards, descendants and filters are refused (JQ0003) - a selector names one member.",
|
|
712
|
+
"type": "string",
|
|
713
|
+
"pattern": "^\\$[.\\[]"
|
|
714
|
+
},
|
|
715
|
+
"seriesSpecPhrase": {
|
|
716
|
+
"description": "$resample / $rolling [series, spec]: an operand expression and a VERBATIM spec literal. $resample returns sorted {at, value, count} buckets one per 'every'; $rolling returns one row per input instant over a window measured in time. (LLM profile: a member-name constraint is relaxed here; the canonical schema enforces it)",
|
|
717
|
+
"type": "object",
|
|
718
|
+
"minProperties": 1,
|
|
719
|
+
"maxProperties": 1,
|
|
720
|
+
"additionalProperties": {
|
|
721
|
+
"type": "array",
|
|
722
|
+
"prefixItems": [
|
|
723
|
+
{
|
|
724
|
+
"$ref": "#/$defs/expression"
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
"$ref": "#/$defs/seriesSpec"
|
|
728
|
+
}
|
|
729
|
+
],
|
|
730
|
+
"items": false,
|
|
731
|
+
"minItems": 2,
|
|
732
|
+
"maxItems": 2
|
|
733
|
+
}
|
|
734
|
+
},
|
|
735
|
+
"asOfSpec": {
|
|
736
|
+
"description": "The $asof spec (QUERY-FORMAT.md section 8.16): a VERBATIM literal. 'by' joins within groups; 'leftAt'/'rightAt' say where each side keeps its instant when the two documents spell it differently. Closed: an unknown member is JQ0003.",
|
|
737
|
+
"type": "object",
|
|
738
|
+
"properties": {
|
|
739
|
+
"direction": {
|
|
740
|
+
"enum": [
|
|
741
|
+
"backward",
|
|
742
|
+
"forward",
|
|
743
|
+
"nearest"
|
|
744
|
+
]
|
|
745
|
+
},
|
|
746
|
+
"tolerance": {
|
|
747
|
+
"$ref": "#/$defs/seriesSpan"
|
|
748
|
+
},
|
|
749
|
+
"by": {
|
|
750
|
+
"$ref": "#/$defs/rowSelector"
|
|
751
|
+
},
|
|
752
|
+
"leftAt": {
|
|
753
|
+
"$ref": "#/$defs/rowSelector"
|
|
754
|
+
},
|
|
755
|
+
"rightAt": {
|
|
756
|
+
"$ref": "#/$defs/rowSelector"
|
|
757
|
+
}
|
|
758
|
+
},
|
|
759
|
+
"additionalProperties": false
|
|
760
|
+
},
|
|
761
|
+
"asOfPhrase": {
|
|
762
|
+
"description": "$asof [left, right] or [left, right, spec]: two operand expressions and an optional VERBATIM spec literal. Answers one {left, right, distance} per left row; a left row with no match keeps right: null and stays in the answer.",
|
|
763
|
+
"type": "object",
|
|
764
|
+
"properties": {
|
|
765
|
+
"$asof": {
|
|
766
|
+
"type": "array",
|
|
767
|
+
"prefixItems": [
|
|
768
|
+
{
|
|
769
|
+
"$ref": "#/$defs/expression"
|
|
770
|
+
},
|
|
771
|
+
{
|
|
772
|
+
"$ref": "#/$defs/expression"
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
"$ref": "#/$defs/asOfSpec"
|
|
776
|
+
}
|
|
777
|
+
],
|
|
778
|
+
"items": false,
|
|
779
|
+
"minItems": 2,
|
|
780
|
+
"maxItems": 3
|
|
781
|
+
}
|
|
782
|
+
},
|
|
783
|
+
"required": [
|
|
784
|
+
"$asof"
|
|
785
|
+
],
|
|
786
|
+
"additionalProperties": false
|
|
787
|
+
},
|
|
788
|
+
"calendarContext": {
|
|
789
|
+
"description": "$time-bucket's optional fourth position: the wall clock its boundaries fall on. UTC is the default and needs nothing; a named 'zone' needs an injected zoneProvider.",
|
|
790
|
+
"type": "object",
|
|
791
|
+
"properties": {
|
|
792
|
+
"zone": {
|
|
793
|
+
"type": "string",
|
|
794
|
+
"minLength": 1
|
|
795
|
+
},
|
|
796
|
+
"offset": {
|
|
797
|
+
"type": "number"
|
|
798
|
+
},
|
|
799
|
+
"disambiguation": {
|
|
800
|
+
"enum": [
|
|
801
|
+
"reject",
|
|
802
|
+
"earlier",
|
|
803
|
+
"later"
|
|
804
|
+
]
|
|
805
|
+
}
|
|
806
|
+
},
|
|
807
|
+
"additionalProperties": false
|
|
808
|
+
},
|
|
809
|
+
"timeBucketPhrase": {
|
|
810
|
+
"description": "$time-bucket [at, every] / [at, every, origin] / [at, every, origin, context]: the instant labelling the bucket 'at' falls in. The first three positions are operand expressions ('origin' may be null for the ladder's own default); the fourth is a VERBATIM calendar context literal.",
|
|
811
|
+
"type": "object",
|
|
812
|
+
"properties": {
|
|
813
|
+
"$time-bucket": {
|
|
814
|
+
"type": "array",
|
|
815
|
+
"prefixItems": [
|
|
816
|
+
{
|
|
817
|
+
"$ref": "#/$defs/expression"
|
|
818
|
+
},
|
|
819
|
+
{
|
|
820
|
+
"$ref": "#/$defs/expression"
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
"$ref": "#/$defs/expression"
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
"$ref": "#/$defs/calendarContext"
|
|
827
|
+
}
|
|
828
|
+
],
|
|
829
|
+
"items": false,
|
|
830
|
+
"minItems": 2,
|
|
831
|
+
"maxItems": 4
|
|
832
|
+
}
|
|
833
|
+
},
|
|
834
|
+
"required": [
|
|
835
|
+
"$time-bucket"
|
|
836
|
+
],
|
|
837
|
+
"additionalProperties": false
|
|
838
|
+
},
|
|
610
839
|
"asClause": {
|
|
611
840
|
"description": "The $as clause: variable-name to JSON Schema literal members, applied per tuple after $for/$let binding and before $where. Each name must be bound by the same phrase's $for (including $at names) or $let - a compiler rule (JQ0005); each binding validates per item at runtime (JQ2008). (LLM profile: a member-name constraint is relaxed here; the canonical schema enforces it)",
|
|
612
841
|
"type": "object",
|
|
@@ -93,7 +93,10 @@
|
|
|
93
93
|
{ "$ref": "#/$defs/geohashPhrase" },
|
|
94
94
|
{ "$ref": "#/$defs/ternaryOperatorPhrase" },
|
|
95
95
|
{ "$ref": "#/$defs/replacePhrase" },
|
|
96
|
-
{ "$ref": "#/$defs/schemaOperatorPhrase" }
|
|
96
|
+
{ "$ref": "#/$defs/schemaOperatorPhrase" },
|
|
97
|
+
{ "$ref": "#/$defs/seriesSpecPhrase" },
|
|
98
|
+
{ "$ref": "#/$defs/asOfPhrase" },
|
|
99
|
+
{ "$ref": "#/$defs/timeBucketPhrase" }
|
|
97
100
|
]
|
|
98
101
|
},
|
|
99
102
|
"mapConstructor": {
|
|
@@ -308,7 +311,7 @@
|
|
|
308
311
|
"$index-of", "$range", "$get",
|
|
309
312
|
"$start-of", "$end-of", "$date-format",
|
|
310
313
|
"$distance", "$within", "$bbox-intersects", "$geo-simplify",
|
|
311
|
-
"$similarity", "$default"
|
|
314
|
+
"$similarity", "$overlaps", "$default"
|
|
312
315
|
]
|
|
313
316
|
},
|
|
314
317
|
"additionalProperties": {
|
|
@@ -433,6 +436,123 @@
|
|
|
433
436
|
"maxItems": 2
|
|
434
437
|
}
|
|
435
438
|
},
|
|
439
|
+
"seriesSpec": {
|
|
440
|
+
"description": "A $resample or $rolling spec (QUERY-FORMAT.md section 8.16): a VERBATIM literal, never an expression, so the width, the aggregate, the fill policy, the wall clock and the row selectors are read once when the query compiles. Closed: an unknown member is JQ0003. 'every'/'width' is an ISO 8601 duration or a count of milliseconds; 'origin'/'start'/'end' are epoch milliseconds or an RFC 3339 string; 'at'/'value' are singular paths where '$' reads as the ROW. A named 'zone' needs an injected zoneProvider - this suite bundles no time-zone database.",
|
|
441
|
+
"type": "object",
|
|
442
|
+
"properties": {
|
|
443
|
+
"every": { "$ref": "#/$defs/seriesSpan" },
|
|
444
|
+
"width": { "$ref": "#/$defs/seriesSpan" },
|
|
445
|
+
"origin": { "$ref": "#/$defs/seriesInstant" },
|
|
446
|
+
"start": { "$ref": "#/$defs/seriesInstant" },
|
|
447
|
+
"end": { "$ref": "#/$defs/seriesInstant" },
|
|
448
|
+
"aggregate": { "enum": ["sum", "mean", "min", "max", "first", "last", "count"] },
|
|
449
|
+
"fill": { "enum": ["omit", "null", "zero", "locf", "linear"] },
|
|
450
|
+
"minPeriods": { "type": "integer", "minimum": 1 },
|
|
451
|
+
"at": { "$ref": "#/$defs/rowSelector" },
|
|
452
|
+
"value": { "$ref": "#/$defs/rowSelector" },
|
|
453
|
+
"zone": { "type": "string", "minLength": 1 },
|
|
454
|
+
"offset": { "type": "number" },
|
|
455
|
+
"disambiguation": { "enum": ["reject", "earlier", "later"] }
|
|
456
|
+
},
|
|
457
|
+
"additionalProperties": false
|
|
458
|
+
},
|
|
459
|
+
"seriesSpan": {
|
|
460
|
+
"description": "A width: an ISO 8601 duration string ('PT1H', 'P1M') or a count of milliseconds. A duration mixing the calendar and clock families ('P1MT1H') is refused by the compiler.",
|
|
461
|
+
"anyOf": [
|
|
462
|
+
{ "type": "string", "minLength": 1 },
|
|
463
|
+
{ "type": "number", "exclusiveMinimum": 0 }
|
|
464
|
+
]
|
|
465
|
+
},
|
|
466
|
+
"seriesInstant": {
|
|
467
|
+
"description": "An instant: epoch milliseconds, or an RFC 3339 string. A full-time names no instant and is refused by the compiler.",
|
|
468
|
+
"anyOf": [
|
|
469
|
+
{ "type": "number" },
|
|
470
|
+
{ "type": "string", "minLength": 1 }
|
|
471
|
+
]
|
|
472
|
+
},
|
|
473
|
+
"rowSelector": {
|
|
474
|
+
"description": "Where a member lives in a source row: a singular JSONPath whose '$' is the ROW rather than the document ('$.on', \"$['recorded at']\", '$.meta.at'). Wildcards, descendants and filters are refused (JQ0003) - a selector names one member.",
|
|
475
|
+
"type": "string",
|
|
476
|
+
"pattern": "^\\$[.\\[]"
|
|
477
|
+
},
|
|
478
|
+
"seriesSpecPhrase": {
|
|
479
|
+
"description": "$resample / $rolling [series, spec]: an operand expression and a VERBATIM spec literal. $resample returns sorted {at, value, count} buckets one per 'every'; $rolling returns one row per input instant over a window measured in time.",
|
|
480
|
+
"type": "object",
|
|
481
|
+
"minProperties": 1,
|
|
482
|
+
"maxProperties": 1,
|
|
483
|
+
"propertyNames": { "enum": ["$resample", "$rolling"] },
|
|
484
|
+
"additionalProperties": {
|
|
485
|
+
"type": "array",
|
|
486
|
+
"prefixItems": [
|
|
487
|
+
{ "$ref": "#/$defs/expression" },
|
|
488
|
+
{ "$ref": "#/$defs/seriesSpec" }
|
|
489
|
+
],
|
|
490
|
+
"items": false,
|
|
491
|
+
"minItems": 2,
|
|
492
|
+
"maxItems": 2
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
"asOfSpec": {
|
|
496
|
+
"description": "The $asof spec (QUERY-FORMAT.md section 8.16): a VERBATIM literal. 'by' joins within groups; 'leftAt'/'rightAt' say where each side keeps its instant when the two documents spell it differently. Closed: an unknown member is JQ0003.",
|
|
497
|
+
"type": "object",
|
|
498
|
+
"properties": {
|
|
499
|
+
"direction": { "enum": ["backward", "forward", "nearest"] },
|
|
500
|
+
"tolerance": { "$ref": "#/$defs/seriesSpan" },
|
|
501
|
+
"by": { "$ref": "#/$defs/rowSelector" },
|
|
502
|
+
"leftAt": { "$ref": "#/$defs/rowSelector" },
|
|
503
|
+
"rightAt": { "$ref": "#/$defs/rowSelector" }
|
|
504
|
+
},
|
|
505
|
+
"additionalProperties": false
|
|
506
|
+
},
|
|
507
|
+
"asOfPhrase": {
|
|
508
|
+
"description": "$asof [left, right] or [left, right, spec]: two operand expressions and an optional VERBATIM spec literal. Answers one {left, right, distance} per left row; a left row with no match keeps right: null and stays in the answer.",
|
|
509
|
+
"type": "object",
|
|
510
|
+
"properties": {
|
|
511
|
+
"$asof": {
|
|
512
|
+
"type": "array",
|
|
513
|
+
"prefixItems": [
|
|
514
|
+
{ "$ref": "#/$defs/expression" },
|
|
515
|
+
{ "$ref": "#/$defs/expression" },
|
|
516
|
+
{ "$ref": "#/$defs/asOfSpec" }
|
|
517
|
+
],
|
|
518
|
+
"items": false,
|
|
519
|
+
"minItems": 2,
|
|
520
|
+
"maxItems": 3
|
|
521
|
+
}
|
|
522
|
+
},
|
|
523
|
+
"required": ["$asof"],
|
|
524
|
+
"additionalProperties": false
|
|
525
|
+
},
|
|
526
|
+
"calendarContext": {
|
|
527
|
+
"description": "$time-bucket's optional fourth position: the wall clock its boundaries fall on. UTC is the default and needs nothing; a named 'zone' needs an injected zoneProvider.",
|
|
528
|
+
"type": "object",
|
|
529
|
+
"properties": {
|
|
530
|
+
"zone": { "type": "string", "minLength": 1 },
|
|
531
|
+
"offset": { "type": "number" },
|
|
532
|
+
"disambiguation": { "enum": ["reject", "earlier", "later"] }
|
|
533
|
+
},
|
|
534
|
+
"additionalProperties": false
|
|
535
|
+
},
|
|
536
|
+
"timeBucketPhrase": {
|
|
537
|
+
"description": "$time-bucket [at, every] / [at, every, origin] / [at, every, origin, context]: the instant labelling the bucket 'at' falls in. The first three positions are operand expressions ('origin' may be null for the ladder's own default); the fourth is a VERBATIM calendar context literal.",
|
|
538
|
+
"type": "object",
|
|
539
|
+
"properties": {
|
|
540
|
+
"$time-bucket": {
|
|
541
|
+
"type": "array",
|
|
542
|
+
"prefixItems": [
|
|
543
|
+
{ "$ref": "#/$defs/expression" },
|
|
544
|
+
{ "$ref": "#/$defs/expression" },
|
|
545
|
+
{ "$ref": "#/$defs/expression" },
|
|
546
|
+
{ "$ref": "#/$defs/calendarContext" }
|
|
547
|
+
],
|
|
548
|
+
"items": false,
|
|
549
|
+
"minItems": 2,
|
|
550
|
+
"maxItems": 4
|
|
551
|
+
}
|
|
552
|
+
},
|
|
553
|
+
"required": ["$time-bucket"],
|
|
554
|
+
"additionalProperties": false
|
|
555
|
+
},
|
|
436
556
|
"asClause": {
|
|
437
557
|
"description": "The $as clause: variable-name to JSON Schema literal members, applied per tuple after $for/$let binding and before $where. Each name must be bound by the same phrase's $for (including $at names) or $let - a compiler rule (JQ0005); each binding validates per item at runtime (JQ2008).",
|
|
438
558
|
"type": "object",
|
package/src/query/normalize.js
CHANGED
|
@@ -433,6 +433,25 @@ const OPERATOR_ALIASES = {
|
|
|
433
433
|
"$nearest-neighbours": "$orderby on a $similarity key, then $subsequence",
|
|
434
434
|
"$nearest-neighbors": "$orderby on a $similarity key, then $subsequence",
|
|
435
435
|
"$top-k": "$orderby then $subsequence", $embed: null, $normalize: null,
|
|
436
|
+
// time series: the spellings a writer arrives with from Timescale,
|
|
437
|
+
// pandas, SQL and kdb+. The bucketing family all points at the two
|
|
438
|
+
// operators that exist - the scalar label and the aggregating one -
|
|
439
|
+
// and the fill policies point at `$resample`, because a fill is a
|
|
440
|
+
// MEMBER of a resample spec rather than an operation of its own
|
|
441
|
+
$time_bucket: "$time-bucket", "$date-bin": "$time-bucket",
|
|
442
|
+
$date_bin: "$time-bucket", $bucket: "$time-bucket",
|
|
443
|
+
"$time-bucket-gapfill": "$resample with a 'fill'",
|
|
444
|
+
$gapfill: "$resample with a 'fill'", $locf: "$resample with fill 'locf'",
|
|
445
|
+
$interpolate: "$resample with fill 'linear'",
|
|
446
|
+
$downsample: "$resample", $upsample: "$resample with a 'fill'",
|
|
447
|
+
$rollup: "$resample", $groupbytime: "$resample",
|
|
448
|
+
"$moving-average": "$rolling with aggregate 'mean'",
|
|
449
|
+
$rollingwindow: "$rolling", "$time-window": "$rolling",
|
|
450
|
+
"$as-of": "$asof", "$asof-join": "$asof", $aj: "$asof",
|
|
451
|
+
"$merge-asof": "$asof", "$latest-at": "$asof",
|
|
452
|
+
$overlap: "$overlaps", "$interval-overlaps": "$overlaps",
|
|
453
|
+
$during: "$overlaps", $meets: null, $abuts: null,
|
|
454
|
+
$now: null, "$current-timestamp": null,
|
|
436
455
|
};
|
|
437
456
|
|
|
438
457
|
// JQ0002 for an unknown $-key, with a "did you mean" suggestion. A
|
|
@@ -577,6 +596,11 @@ function argCards(args) {
|
|
|
577
596
|
return cards;
|
|
578
597
|
}
|
|
579
598
|
|
|
599
|
+
// The operators that read a calendar boundary, and so may be given a
|
|
600
|
+
// named zone. `$asof` and `$overlaps` are pure instant arithmetic and
|
|
601
|
+
// have no clock to resolve.
|
|
602
|
+
const CLOCK_OPERATORS = new Set(['$time-bucket', '$resample', '$rolling']);
|
|
603
|
+
|
|
580
604
|
// A registry operator call: arity and shape come uniformly from the
|
|
581
605
|
// table's `params` descriptor (JQ0003), the static cardinality from its
|
|
582
606
|
// `result` - individual operators never re-check structure.
|
|
@@ -590,6 +614,11 @@ function normalizeOperatorCall(key, entry, arg, docPath, opPath, scope, ctx) {
|
|
|
590
614
|
// configurable through the compilation's limits (compileOp hands the
|
|
591
615
|
// node through to the entry's compile)
|
|
592
616
|
if (key === '$range' && ctx.limits !== null) node.limits = ctx.limits;
|
|
617
|
+
// the series operators resolve their wall clock when the query
|
|
618
|
+
// compiles, and a named zone needs the tzdb this suite does not bundle
|
|
619
|
+
// (SERIES D7). The provider is a compilation capability, like a
|
|
620
|
+
// collation, so it reaches the entry the same way $range's guard does
|
|
621
|
+
if (ctx.zoneProvider !== null && CLOCK_OPERATORS.has(key)) node.zoneProvider = ctx.zoneProvider;
|
|
593
622
|
return Object.freeze(node);
|
|
594
623
|
}
|
|
595
624
|
|
|
@@ -1258,6 +1287,19 @@ function validateNamedFunctions(value, what) {
|
|
|
1258
1287
|
return value;
|
|
1259
1288
|
}
|
|
1260
1289
|
|
|
1290
|
+
// Validate the injected time-zone provider (options.zoneProvider): the
|
|
1291
|
+
// two-question seam SERIES D7 fixes, because this suite bundles no
|
|
1292
|
+
// tzdb and a JSON document cannot carry one. Violations are host
|
|
1293
|
+
// programming errors (TypeError), like options.extensions.
|
|
1294
|
+
function validateZoneProvider(value) {
|
|
1295
|
+
if (value === null || typeof value !== 'object'
|
|
1296
|
+
|| typeof value.toParts !== 'function' || typeof value.toEpoch !== 'function') {
|
|
1297
|
+
throw new TypeError('options.zoneProvider must be an object with'
|
|
1298
|
+
+ ' toParts(epoch, zone) and toEpoch(parts, zone, disambiguation)');
|
|
1299
|
+
}
|
|
1300
|
+
return value;
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1261
1303
|
// The known limits (section 8.12). Only limits the engine actually
|
|
1262
1304
|
// enforces are accepted - an accepted-but-unenforced limit would be a
|
|
1263
1305
|
// silent false guarantee.
|
|
@@ -1423,6 +1465,7 @@ export function normalizeQuery(doc, options = {}) {
|
|
|
1423
1465
|
const extensions = options.extensions == null ? null : validateExtensions(options.extensions);
|
|
1424
1466
|
const functions = options.functions == null ? null : validateNamedFunctions(options.functions, 'functions');
|
|
1425
1467
|
const collations = options.collations == null ? null : validateNamedFunctions(options.collations, 'collations');
|
|
1468
|
+
const zoneProvider = options.zoneProvider == null ? null : validateZoneProvider(options.zoneProvider);
|
|
1426
1469
|
const limits = options.limits == null ? null : validateLimits(options.limits);
|
|
1427
1470
|
const declaredExternals = options.externals == null
|
|
1428
1471
|
? null
|
|
@@ -1436,7 +1479,7 @@ export function normalizeQuery(doc, options = {}) {
|
|
|
1436
1479
|
: { pathFunctions: options.pathFunctions };
|
|
1437
1480
|
const ctx = {
|
|
1438
1481
|
nextSlot: 1, externals: new Map(), compileTypeTest, extensions,
|
|
1439
|
-
functions, collations, limits, pathOptions, declaredExternals,
|
|
1482
|
+
functions, collations, zoneProvider, limits, pathOptions, declaredExternals,
|
|
1440
1483
|
// package-internal: set only by analyzeQuery (Appendix C.1); the
|
|
1441
1484
|
// compile entry point never passes it
|
|
1442
1485
|
analysis: options.analysis === true,
|