Merge "Merge branch 'gerrit/goldfish' into 'master'"
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinNode.java
index b988ad9..26707e1 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinNode.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinNode.java
@@ -300,10 +300,10 @@
parent.getInputs().get(0).setValue(deepCopyofScan);
finalDatasetCard = origDatasetCard = idxDetails.getSourceCardinality();
sampleCard = Math.min(idxDetails.getSampleCardinalityTarget(), origDatasetCard);
- boolean unnest = joinEnum.findUnnestOp(selOp);
+ boolean unnest = joinEnum.findUnnestOp(leafInput);
if (unnest) {
ILogicalExpression saveExpr = selOp.getCondition().getValue();
- double unnestSampleCard = joinEnum.stats.computeUnnestedOriginalCardinality(selOp);
+ double unnestSampleCard = joinEnum.stats.computeUnnestedOriginalCardinality(leafInput);
selOp.getCondition().setValue(saveExpr); // restore the expression
unnestFactor = unnestSampleCard / sampleCard;
sampleCard = unnestSampleCard;
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/Stats.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/Stats.java
index 06a3c4b..c6f274f 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/Stats.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/Stats.java
@@ -538,11 +538,11 @@
return record.numberOfFields();
}
- public double computeUnnestedOriginalCardinality(SelectOperator selOp) throws AlgebricksException {
+ public double computeUnnestedOriginalCardinality(ILogicalOperator op) throws AlgebricksException {
// Replace ALL SELECTS with TRUE, restore them after running the sampling query.
- List<ILogicalExpression> selExprs = storeSelectConditionsAndMakeThemTrue(selOp, null);
- List<List<IAObject>> result = runSamplingQuery(optCtx, selOp);
- restoreAllSelectConditions(selOp, selExprs, null);
+ List<ILogicalExpression> selExprs = storeSelectConditionsAndMakeThemTrue(op, null);
+ List<List<IAObject>> result = runSamplingQuery(optCtx, op);
+ restoreAllSelectConditions(op, selExprs, null);
return findPredicateCardinality(result, false);
}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/filter/subplan/subplan.042.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/filter/subplan/subplan.042.plan
index 7fe9bcc..6428718 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/filter/subplan/subplan.042.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/filter/subplan/subplan.042.plan
@@ -1,72 +1,72 @@
-distribute result [$$70] [cardinality: 6.0, op-cost: 0.0, total-cost: 28.6]
+distribute result [$$70] [cardinality: 6.0, op-cost: 0.0, total-cost: 23.6]
-- DISTRIBUTE_RESULT |UNPARTITIONED|
- exchange [cardinality: 6.0, op-cost: 0.0, total-cost: 28.6]
+ exchange [cardinality: 6.0, op-cost: 0.0, total-cost: 23.6]
-- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
- aggregate [$$70] <- [agg-sql-sum($$76)] [cardinality: 6.0, op-cost: 0.0, total-cost: 28.6]
+ aggregate [$$70] <- [agg-sql-sum($$76)] [cardinality: 6.0, op-cost: 0.0, total-cost: 23.6]
-- AGGREGATE |UNPARTITIONED|
- exchange [cardinality: 6.0, op-cost: 0.0, total-cost: 28.6]
+ exchange [cardinality: 6.0, op-cost: 0.0, total-cost: 23.6]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- aggregate [$$76] <- [agg-sql-count(1)] [cardinality: 6.0, op-cost: 0.0, total-cost: 28.6]
+ aggregate [$$76] <- [agg-sql-count(1)] [cardinality: 6.0, op-cost: 0.0, total-cost: 23.6]
-- AGGREGATE |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 0.0, total-cost: 28.6]
+ exchange [cardinality: 6.0, op-cost: 0.0, total-cost: 23.6]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (or(eq($$71, "7"), neq($$69, 0))) [cardinality: 6.0, op-cost: 12.6, total-cost: 28.6]
+ join (or(eq($$71, "7"), neq($$69, 0))) [cardinality: 6.0, op-cost: 12.6, total-cost: 23.6]
-- NESTED_LOOP |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ exchange [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$71]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$71]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$71] <- [$$p.getField("arrayOrObject").getField("text")] [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ assign [$$71] <- [$$p.getField("arrayOrObject").getField("text")] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- ASSIGN |PARTITIONED|
- project ([$$p]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$p]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$p] <- [$$b2] [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ assign [$$p] <- [$$b2] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ exchange [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- replicate [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ replicate [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- REPLICATE |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$b2]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$b2]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$68, $$b2] <- test.ColumnDataset project ({arrayOrObject:<[{text:any}],{text:any}>}) [cardinality: 6.0, op-cost: 6.0, total-cost: 6.0]
+ data-scan []<-[$$68, $$b2] <- test.ColumnDataset project ({arrayOrObject:<[{text:any}],{text:any}>}) [cardinality: 1.0, op-cost: 1.0, total-cost: 1.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
empty-tuple-source [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- BROADCAST_EXCHANGE |PARTITIONED|
- aggregate [$$69] <- [agg-sum($$75)] [cardinality: 1.0, op-cost: 0.0, total-cost: 6.0]
+ aggregate [$$69] <- [agg-sum($$75)] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- AGGREGATE |UNPARTITIONED|
- exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- aggregate [$$75] <- [agg-count(1)] [cardinality: 1.0, op-cost: 0.0, total-cost: 6.0]
+ aggregate [$$75] <- [agg-count(1)] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- AGGREGATE |PARTITIONED|
- select (eq($$ao.getField("text"), "1")) [cardinality: 1.0, op-cost: 0.0, total-cost: 6.0]
+ select (eq($$ao.getField("text"), "1")) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_SELECT |PARTITIONED|
- project ([$$ao]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$ao]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- unnest $$ao <- scan-collection($$72) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ unnest $$ao <- scan-collection($$72) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- UNNEST |PARTITIONED|
- project ([$$72]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$72]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$72] <- [$$b2.getField("arrayOrObject")] [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ assign [$$72] <- [$$b2.getField("arrayOrObject")] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- replicate [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ replicate [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- REPLICATE |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$b2]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$b2]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$68, $$b2] <- test.ColumnDataset project ({arrayOrObject:<[{text:any}],{text:any}>}) [cardinality: 6.0, op-cost: 6.0, total-cost: 6.0]
+ data-scan []<-[$$68, $$b2] <- test.ColumnDataset project ({arrayOrObject:<[{text:any}],{text:any}>}) [cardinality: 1.0, op-cost: 1.0, total-cost: 1.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/filter/subplan/subplan.062.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/filter/subplan/subplan.062.plan
index 70f874e..345fc12 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/filter/subplan/subplan.062.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/filter/subplan/subplan.062.plan
@@ -1,8 +1,8 @@
-distribute result [$$63] [cardinality: 2.1, op-cost: 0.0, total-cost: 20.41]
+distribute result [$$63] [cardinality: 2.1, op-cost: 0.0, total-cost: 15.41]
-- DISTRIBUTE_RESULT |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 20.41]
+ exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 15.41]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (true) [cardinality: 2.1, op-cost: 4.41, total-cost: 20.41]
+ join (true) [cardinality: 2.1, op-cost: 4.41, total-cost: 15.41]
-- NESTED_LOOP |PARTITIONED|
exchange [cardinality: 1.0, op-cost: 0.0, total-cost: 6.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
@@ -10,59 +10,59 @@
-- STREAM_PROJECT |PARTITIONED|
select (eq($$p.getField("arrayOrObject").getField("text"), "7")) [cardinality: 1.0, op-cost: 0.0, total-cost: 6.0]
-- STREAM_SELECT |PARTITIONED|
- project ([$$p]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$p]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$p] <- [$$p2] [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ assign [$$p] <- [$$p2] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ exchange [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- replicate [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ replicate [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- REPLICATE |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$p2]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$p2]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$62, $$p2] <- test.ColumnDataset project ({arrayOrObject:<[{text:any}],{text:any}>}) filter on: or(eq($$p2.getField("arrayOrObject").getField("text"), "7"), and(ge(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "1"), le(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "2"))) range-filter on: or(eq($$p2.getField("arrayOrObject").getField("text"), "7"), and(ge(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "1"), le(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "2"))) [cardinality: 6.0, op-cost: 6.0, total-cost: 6.0]
+ data-scan []<-[$$62, $$p2] <- test.ColumnDataset project ({arrayOrObject:<[{text:any}],{text:any}>}) filter on: or(eq($$p2.getField("arrayOrObject").getField("text"), "7"), and(ge(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "1"), le(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "2"))) range-filter on: or(eq($$p2.getField("arrayOrObject").getField("text"), "7"), and(ge(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "1"), le(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "2"))) [cardinality: 1.0, op-cost: 1.0, total-cost: 1.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
empty-tuple-source [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- BROADCAST_EXCHANGE |PARTITIONED|
- aggregate [$$63] <- [agg-sql-sum($$67)] [cardinality: 1.0, op-cost: 0.0, total-cost: 6.0]
+ aggregate [$$63] <- [agg-sql-sum($$67)] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- AGGREGATE |UNPARTITIONED|
- exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- aggregate [$$67] <- [agg-sql-count(1)] [cardinality: 1.0, op-cost: 0.0, total-cost: 6.0]
+ aggregate [$$67] <- [agg-sql-count(1)] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- AGGREGATE |PARTITIONED|
- select (and(ge($$60, "1"), le($$60, "2"))) [cardinality: 1.0, op-cost: 0.0, total-cost: 6.0]
+ select (and(ge($$60, "1"), le($$60, "2"))) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_SELECT |PARTITIONED|
- project ([$$60]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$60]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$60] <- [$$ao.getField("text")] [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ assign [$$60] <- [$$ao.getField("text")] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- ASSIGN |PARTITIONED|
- project ([$$ao]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$ao]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- unnest $$ao <- scan-collection($$65) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ unnest $$ao <- scan-collection($$65) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- UNNEST |PARTITIONED|
- project ([$$65]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$65]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$65] <- [$$p2.getField("arrayOrObject")] [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ assign [$$65] <- [$$p2.getField("arrayOrObject")] [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- replicate [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ replicate [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- REPLICATE |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$p2]) [cardinality: 6.0, op-cost: 0.0, total-cost: 6.0]
+ project ([$$p2]) [cardinality: 1.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 6.0, op-cost: 4.0, total-cost: 10.0]
+ exchange [cardinality: 1.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$62, $$p2] <- test.ColumnDataset project ({arrayOrObject:<[{text:any}],{text:any}>}) filter on: or(eq($$p2.getField("arrayOrObject").getField("text"), "7"), and(ge(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "1"), le(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "2"))) range-filter on: or(eq($$p2.getField("arrayOrObject").getField("text"), "7"), and(ge(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "1"), le(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "2"))) [cardinality: 6.0, op-cost: 6.0, total-cost: 6.0]
+ data-scan []<-[$$62, $$p2] <- test.ColumnDataset project ({arrayOrObject:<[{text:any}],{text:any}>}) filter on: or(eq($$p2.getField("arrayOrObject").getField("text"), "7"), and(ge(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "1"), le(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "2"))) range-filter on: or(eq($$p2.getField("arrayOrObject").getField("text"), "7"), and(ge(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "1"), le(scan-collection($$p2.getField("arrayOrObject")).getField("text"), "2"))) [cardinality: 1.0, op-cost: 1.0, total-cost: 1.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|