asterixdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From buyin...@apache.org
Subject [29/29] incubator-asterixdb git commit: Supports Left Outer Join and Left Outer Unnest in SQL++.
Date Sat, 04 Jun 2016 02:44:33 GMT
Supports Left Outer Join and Left Outer Unnest in SQL++.

- change record format to allow MISSING value for an optional field;
- support roundtrips of MISSING valued closed fields for load and insert;
- suppress fields with MISSING values in result printer;
- fix ByNameToByIndexFieldAccessRule and LoadRecordFieldsRule;
- update test queries and results.

Change-Id: Ie0caea9c1842d93541b067a1193d117af30d8dfc
Reviewed-on: https://asterix-gerrit.ics.uci.edu/899
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <tillw@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/commit/b0fe0ac0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/tree/b0fe0ac0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/diff/b0fe0ac0

Branch: refs/heads/master
Commit: b0fe0ac0c73164fc69f2b35a12c012cac2a3dc91
Parents: dde37e3
Author: Yingyi Bu <yingyi@couchbase.com>
Authored: Fri Jun 3 18:20:48 2016 -0700
Committer: Yingyi Bu <buyingyi@gmail.com>
Committed: Fri Jun 3 19:43:35 2016 -0700

----------------------------------------------------------------------
 .../physical/InvertedIndexPOperator.java        |    4 +-
 .../asterix/optimizer/base/RuleCollections.java |   60 +-
 .../rules/ByNameToByIndexFieldAccessRule.java   |  134 +-
 .../rules/IntroduceDynamicTypeCastRule.java     |    6 +-
 ...IntroduceSecondaryIndexInsertDeleteRule.java |    8 +-
 .../optimizer/rules/LoadRecordFieldsRule.java   |  141 +-
 ...moveLeftOuterUnnestForLeftOuterJoinRule.java |  281 ++++
 .../rules/SetClosedRecordConstructorsRule.java  |   18 +-
 .../SweepIllegalNonfunctionalFunctions.java     |    4 +-
 .../subplan/InlineAllNtsInSubplanVisitor.java   |    5 +-
 ...neLeftNtsInSubplanJoinFlatteningVisitor.java |    5 +-
 .../SubplanSpecialFlatteningCheckVisitor.java   |    4 +-
 .../SqlppExpressionToPlanTranslator.java        |  104 +-
 .../asterix/translator/TypeTranslator.java      |   18 +-
 .../asterix/test/sqlpp/ParserTestExecutor.java  |    3 +-
 .../dataset_with_meta-1.1.adm                   |    2 +-
 .../dataset_with_meta-2.1.adm                   |    2 +-
 .../dataset_with_meta-2.3.adm                   |    2 +-
 .../dataset_with_meta-4.3.adm                   |    2 +-
 .../dataset_with_meta-5.3.adm                   |    2 +-
 .../issue_251_dataset_hint_1.1.adm              |  Bin 654 -> 629 bytes
 .../issue_251_dataset_hint_2.1.adm              |    2 +-
 .../issue_251_dataset_hint_3.1.adm              |    2 +-
 .../issue_251_dataset_hint_4.1.adm              |    2 +-
 .../metadata/results/basic/meta02/meta02.1.adm  |    2 +-
 .../metadata/results/basic/meta09/meta09.1.adm  |    2 +-
 .../metadata_dataset/metadata_dataset.1.adm     |   26 +-
 .../metadata_datatype/metadata_datatype.1.adm   |  124 +-
 .../verify_failure_previous_success.1.adm       |   20 +-
 .../optimizerts/queries/loj-core.sqlpp          |   57 +
 .../optimizerts/queries/loj-sugar.sqlpp         |   53 +
 .../resources/optimizerts/results/loj-core.plan |   24 +
 .../optimizerts/results/loj-sugar.plan          |   24 +
 .../optimizerts/results/query-issue562.plan     |   28 +-
 .../binary_null/binary_null.1.ddl.aql           |   20 -
 .../binary_null/binary_null.1.query.aql         |   28 +
 .../binary_null/binary_null.2.update.aql        |   18 -
 .../binary_null/binary_null.3.query.aql         |   30 -
 .../double_null/double_null.1.ddl.aql           |   21 -
 .../double_null/double_null.1.query.aql         |   28 +
 .../double_null/double_null.2.update.aql        |   18 -
 .../double_null/double_null.3.query.aql         |   30 -
 .../comparison/float_null/float_null.1.ddl.aql  |   21 -
 .../float_null/float_null.1.query.aql           |   28 +
 .../float_null/float_null.2.update.aql          |   18 -
 .../float_null/float_null.3.query.aql           |   30 -
 .../comparison/int16_null/int16_null.1.ddl.aql  |   22 -
 .../int16_null/int16_null.1.query.aql           |   28 +
 .../int16_null/int16_null.2.update.aql          |   18 -
 .../int16_null/int16_null.3.query.aql           |   30 -
 .../comparison/int32_null/int32_null.1.ddl.aql  |   22 -
 .../int32_null/int32_null.1.query.aql           |   28 +
 .../int32_null/int32_null.2.update.aql          |   18 -
 .../int32_null/int32_null.3.query.aql           |   28 -
 .../comparison/int64_null/int64_null.1.ddl.aql  |   20 -
 .../int64_null/int64_null.1.query.aql           |   28 +
 .../int64_null/int64_null.2.update.aql          |   18 -
 .../int64_null/int64_null.3.query.aql           |   30 -
 .../comparison/int8_null/int8_null.1.ddl.aql    |   20 -
 .../comparison/int8_null/int8_null.1.query.aql  |   28 +
 .../comparison/int8_null/int8_null.2.update.aql |   18 -
 .../comparison/int8_null/int8_null.3.query.aql  |   30 -
 .../string_null/string_null.1.ddl.aql           |   20 -
 .../string_null/string_null.1.query.aql         |   28 +
 .../string_null/string_null.2.update.aql        |   18 -
 .../string_null/string_null.3.query.aql         |   30 -
 .../numeric/add_double/add_double.1.ddl.aql     |   21 -
 .../numeric/add_double/add_double.1.query.aql   |   27 +
 .../numeric/add_double/add_double.2.update.aql  |   18 -
 .../numeric/add_double/add_double.3.query.aql   |   29 -
 .../numeric/add_float/add_float.1.ddl.aql       |   21 -
 .../numeric/add_float/add_float.1.query.aql     |   27 +
 .../numeric/add_float/add_float.2.update.aql    |   18 -
 .../numeric/add_float/add_float.3.query.aql     |   29 -
 .../numeric/add_int16/add_int16.1.ddl.aql       |   21 -
 .../numeric/add_int16/add_int16.1.query.aql     |   27 +
 .../numeric/add_int16/add_int16.2.update.aql    |   18 -
 .../numeric/add_int16/add_int16.3.query.aql     |   29 -
 .../numeric/add_int32/add_int32.1.ddl.aql       |   21 -
 .../numeric/add_int32/add_int32.1.query.aql     |   27 +
 .../numeric/add_int32/add_int32.2.update.aql    |   18 -
 .../numeric/add_int32/add_int32.3.query.aql     |   29 -
 .../numeric/add_int64/add_int64.1.ddl.aql       |   21 -
 .../numeric/add_int64/add_int64.1.query.aql     |   27 +
 .../numeric/add_int64/add_int64.2.update.aql    |   18 -
 .../numeric/add_int64/add_int64.3.query.aql     |   29 -
 .../queries/numeric/add_int8/add_int8.1.ddl.aql |   21 -
 .../numeric/add_int8/add_int8.1.query.aql       |   27 +
 .../numeric/add_int8/add_int8.2.update.aql      |   18 -
 .../numeric/add_int8/add_int8.3.query.aql       |   29 -
 .../divide_double/divide_double.1.ddl.aql       |   21 -
 .../divide_double/divide_double.1.query.aql     |   27 +
 .../divide_double/divide_double.2.update.aql    |   18 -
 .../divide_double/divide_double.3.query.aql     |   29 -
 .../numeric/divide_float/divide_float.1.ddl.aql |   21 -
 .../divide_float/divide_float.1.query.aql       |   27 +
 .../divide_float/divide_float.2.update.aql      |   18 -
 .../divide_float/divide_float.3.query.aql       |   29 -
 .../numeric/divide_int16/divide_int16.1.ddl.aql |   21 -
 .../divide_int16/divide_int16.1.query.aql       |   27 +
 .../divide_int16/divide_int16.2.update.aql      |   18 -
 .../divide_int16/divide_int16.3.query.aql       |   29 -
 .../numeric/divide_int32/divide_int32.1.ddl.aql |   21 -
 .../divide_int32/divide_int32.1.query.aql       |   27 +
 .../divide_int32/divide_int32.2.update.aql      |   18 -
 .../divide_int32/divide_int32.3.query.aql       |   29 -
 .../numeric/divide_int64/divide_int64.1.ddl.aql |   21 -
 .../divide_int64/divide_int64.1.query.aql       |   27 +
 .../divide_int64/divide_int64.2.update.aql      |   18 -
 .../divide_int64/divide_int64.3.query.aql       |   30 -
 .../numeric/divide_int8/divide_int8.1.ddl.aql   |   21 -
 .../numeric/divide_int8/divide_int8.1.query.aql |   27 +
 .../divide_int8/divide_int8.2.update.aql        |   18 -
 .../numeric/divide_int8/divide_int8.3.query.aql |   29 -
 .../multiply_double/multiply_double.1.ddl.aql   |   21 -
 .../multiply_double/multiply_double.1.query.aql |   27 +
 .../multiply_double.2.update.aql                |   18 -
 .../multiply_double/multiply_double.3.query.aql |   29 -
 .../multiply_float/multiply_float.1.ddl.aql     |   21 -
 .../multiply_float/multiply_float.1.query.aql   |   27 +
 .../multiply_float/multiply_float.2.update.aql  |   18 -
 .../multiply_float/multiply_float.3.query.aql   |   29 -
 .../multiply_int16/multiply_int16.1.ddl.aql     |   21 -
 .../multiply_int16/multiply_int16.1.query.aql   |   27 +
 .../multiply_int16/multiply_int16.2.update.aql  |   18 -
 .../multiply_int16/multiply_int16.3.query.aql   |   29 -
 .../multiply_int32/multiply_int32.1.ddl.aql     |   21 -
 .../multiply_int32/multiply_int32.1.query.aql   |   27 +
 .../multiply_int32/multiply_int32.2.update.aql  |   18 -
 .../multiply_int32/multiply_int32.3.query.aql   |   29 -
 .../multiply_int64/multiply_int64.1.ddl.aql     |   21 -
 .../multiply_int64/multiply_int64.1.query.aql   |   27 +
 .../multiply_int64/multiply_int64.2.update.aql  |   18 -
 .../multiply_int64/multiply_int64.3.query.aql   |   29 -
 .../multiply_int8/multiply_int8.1.ddl.aql       |   21 -
 .../multiply_int8/multiply_int8.2.update.aql    |   18 -
 .../multiply_int8/multiply_int8.3.query.aql     |    6 +-
 .../subtract_double/subtract_double.1.ddl.aql   |   21 -
 .../subtract_double/subtract_double.1.query.aql |   27 +
 .../subtract_double.2.update.aql                |   18 -
 .../subtract_double/subtract_double.3.query.aql |   29 -
 .../subtract_float/subtract_float.1.ddl.aql     |   21 -
 .../subtract_float/subtract_float.1.query.aql   |   27 +
 .../subtract_float/subtract_float.2.update.aql  |   18 -
 .../subtract_float/subtract_float.3.query.aql   |   29 -
 .../subtract_int16/subtract_int16.1.ddl.aql     |   21 -
 .../subtract_int16/subtract_int16.1.query.aql   |   27 +
 .../subtract_int16/subtract_int16.2.update.aql  |   18 -
 .../subtract_int16/subtract_int16.3.query.aql   |   29 -
 .../subtract_int32/subtract_int32.1.ddl.aql     |   21 -
 .../subtract_int32/subtract_int32.1.query.aql   |   27 +
 .../subtract_int32/subtract_int32.2.update.aql  |   18 -
 .../subtract_int32/subtract_int32.3.query.aql   |   29 -
 .../subtract_int64/subtract_int64.1.ddl.aql     |   21 -
 .../subtract_int64/subtract_int64.1.query.aql   |   27 +
 .../subtract_int64/subtract_int64.2.update.aql  |   18 -
 .../subtract_int64/subtract_int64.3.query.aql   |   29 -
 .../subtract_int8/subtract_int8.1.ddl.aql       |   21 -
 .../subtract_int8/subtract_int8.1.query.aql     |   27 +
 .../subtract_int8/subtract_int8.2.update.aql    |   18 -
 .../subtract_int8/subtract_int8.3.query.aql     |   29 -
 .../unary-minus_double_02.1.ddl.aql             |   21 -
 .../unary-minus_double_02.1.query.aql           |   24 +
 .../unary-minus_double_02.2.update.aql          |   18 -
 .../unary-minus_double_02.3.query.aql           |   25 -
 .../unary-minus_null/unary-minus_null.1.ddl.aql |   21 -
 .../unary-minus_null.1.query.aql                |   21 +
 .../unary-minus_null.2.update.aql               |   18 -
 .../unary-minus_null.3.query.aql                |   23 -
 .../tinysocial-suite.12.query.aql               |    2 +-
 .../tinysocial-suite.13.query.aql               |    2 +-
 .../binary_missing/binary_missing.1.query.sqlpp |   21 +
 .../binary_null/binary_null.1.ddl.sqlpp         |   22 -
 .../binary_null/binary_null.1.query.sqlpp       |   21 +
 .../binary_null/binary_null.2.update.sqlpp      |   19 -
 .../binary_null/binary_null.3.query.sqlpp       |   23 -
 .../double_missing/double_missing.1.query.sqlpp |   21 +
 .../double_null/double_null.1.ddl.sqlpp         |   22 -
 .../double_null/double_null.1.query.sqlpp       |   21 +
 .../double_null/double_null.2.update.sqlpp      |   19 -
 .../double_null/double_null.3.query.sqlpp       |   23 -
 .../float_missing/float_missing.1.query.sqlpp   |   21 +
 .../float_null/float_null.1.ddl.sqlpp           |   22 -
 .../float_null/float_null.1.query.sqlpp         |   21 +
 .../float_null/float_null.2.update.sqlpp        |   19 -
 .../float_null/float_null.3.query.sqlpp         |   23 -
 .../int16_missing/int16_missing.1.query.sqlpp   |   21 +
 .../int16_null/int16_null.1.ddl.sqlpp           |   22 -
 .../int16_null/int16_null.1.query.sqlpp         |   21 +
 .../int16_null/int16_null.2.update.sqlpp        |   19 -
 .../int16_null/int16_null.3.query.sqlpp         |   23 -
 .../int32_missing/int32_missing.1.query.sqlpp   |   20 +
 .../int32_null/int32_null.1.ddl.sqlpp           |   25 -
 .../int32_null/int32_null.1.query.sqlpp         |   20 +
 .../int32_null/int32_null.2.update.sqlpp        |   19 -
 .../int32_null/int32_null.3.query.sqlpp         |   20 -
 .../int64_missing/int64_missing.1.query.sqlpp   |   21 +
 .../int64_null/int64_null.1.ddl.sqlpp           |   22 -
 .../int64_null/int64_null.1.query.sqlpp         |   20 +
 .../int64_null/int64_null.2.update.sqlpp        |   19 -
 .../int64_null/int64_null.3.query.sqlpp         |   23 -
 .../int8_missing/int8_missing.1.query.sqlpp     |   21 +
 .../comparison/int8_null/int8_null.1.ddl.sqlpp  |   22 -
 .../int8_null/int8_null.1.query.sqlpp           |   21 +
 .../int8_null/int8_null.2.update.sqlpp          |   19 -
 .../int8_null/int8_null.3.query.sqlpp           |   23 -
 .../string_missing/string_missing.1.query.sqlpp |   20 +
 .../string_null/string_null.1.ddl.sqlpp         |   22 -
 .../string_null/string_null.1.query.sqlpp       |   20 +
 .../string_null/string_null.2.update.sqlpp      |   19 -
 .../string_null/string_null.3.query.sqlpp       |   23 -
 .../loj-01-core/loj-01.1.ddl.sqlpp              |   47 +
 .../loj-01-core/loj-01.2.update.sqlpp           |  Bin 0 -> 1111 bytes
 .../loj-01-core/loj-01.3.query.sqlpp            |   32 +
 .../loj-01-sugar/loj-01.1.ddl.sqlpp             |   47 +
 .../loj-01-sugar/loj-01.2.update.sqlpp          |  Bin 0 -> 1111 bytes
 .../loj-01-sugar/loj-01.3.query.sqlpp           |   28 +
 .../comparison/comparison.1.query.sqlpp         |   20 +
 .../field-access/field-access.1.query.sqlpp     |    2 +-
 .../numeric/add_double/add_double.1.ddl.sqlpp   |   22 -
 .../numeric/add_double/add_double.1.query.sqlpp |   21 +
 .../add_double/add_double.2.update.sqlpp        |   19 -
 .../numeric/add_double/add_double.3.query.sqlpp |   23 -
 .../numeric/add_float/add_float.1.ddl.sqlpp     |   22 -
 .../numeric/add_float/add_float.1.query.sqlpp   |   21 +
 .../numeric/add_float/add_float.2.update.sqlpp  |   19 -
 .../numeric/add_float/add_float.3.query.sqlpp   |   23 -
 .../numeric/add_int16/add_int16.1.ddl.sqlpp     |   22 -
 .../numeric/add_int16/add_int16.1.query.sqlpp   |   21 +
 .../numeric/add_int16/add_int16.2.update.sqlpp  |   19 -
 .../numeric/add_int16/add_int16.3.query.sqlpp   |   23 -
 .../numeric/add_int32/add_int32.1.ddl.sqlpp     |   22 -
 .../numeric/add_int32/add_int32.1.query.sqlpp   |   21 +
 .../numeric/add_int32/add_int32.2.update.sqlpp  |   19 -
 .../numeric/add_int32/add_int32.3.query.sqlpp   |   23 -
 .../numeric/add_int64/add_int64.1.ddl.sqlpp     |   22 -
 .../numeric/add_int64/add_int64.1.query.sqlpp   |   21 +
 .../numeric/add_int64/add_int64.2.update.sqlpp  |   19 -
 .../numeric/add_int64/add_int64.3.query.sqlpp   |   23 -
 .../numeric/add_int8/add_int8.1.ddl.sqlpp       |   22 -
 .../numeric/add_int8/add_int8.2.update.sqlpp    |   19 -
 .../numeric/add_int8/add_int8.3.query.sqlpp     |    4 +-
 .../divide_double/divide_double.1.ddl.sqlpp     |   22 -
 .../divide_double/divide_double.1.query.sqlpp   |   21 +
 .../divide_double/divide_double.2.update.sqlpp  |   19 -
 .../divide_double/divide_double.3.query.sqlpp   |   23 -
 .../divide_float/divide_float.1.ddl.sqlpp       |   22 -
 .../divide_float/divide_float.1.query.sqlpp     |   20 +
 .../divide_float/divide_float.2.update.sqlpp    |   19 -
 .../divide_float/divide_float.3.query.sqlpp     |   23 -
 .../divide_int16/divide_int16.1.ddl.sqlpp       |   22 -
 .../divide_int16/divide_int16.1.query.sqlpp     |   20 +
 .../divide_int16/divide_int16.2.update.sqlpp    |   19 -
 .../divide_int16/divide_int16.3.query.sqlpp     |   23 -
 .../divide_int32/divide_int32.1.ddl.sqlpp       |   22 -
 .../divide_int32/divide_int32.1.query.sqlpp     |   21 +
 .../divide_int32/divide_int32.2.update.sqlpp    |   19 -
 .../divide_int32/divide_int32.3.query.sqlpp     |   23 -
 .../divide_int64/divide_int64.1.ddl.sqlpp       |   22 -
 .../divide_int64/divide_int64.1.query.sqlpp     |   20 +
 .../divide_int64/divide_int64.2.update.sqlpp    |   19 -
 .../divide_int64/divide_int64.3.query.sqlpp     |   23 -
 .../numeric/divide_int8/divide_int8.1.ddl.sqlpp |   22 -
 .../divide_int8/divide_int8.1.query.sqlpp       |   21 +
 .../divide_int8/divide_int8.2.update.sqlpp      |   19 -
 .../divide_int8/divide_int8.3.query.sqlpp       |   23 -
 .../multiply_double/multiply_double.1.ddl.sqlpp |   22 -
 .../multiply_double.1.query.sqlpp               |   21 +
 .../multiply_double.2.update.sqlpp              |   19 -
 .../multiply_double.3.query.sqlpp               |   23 -
 .../multiply_float/multiply_float.1.ddl.sqlpp   |   22 -
 .../multiply_float/multiply_float.1.query.sqlpp |   21 +
 .../multiply_float.2.update.sqlpp               |   19 -
 .../multiply_float/multiply_float.3.query.sqlpp |   23 -
 .../multiply_int16/multiply_int16.1.ddl.sqlpp   |   22 -
 .../multiply_int16/multiply_int16.1.query.sqlpp |   21 +
 .../multiply_int16.2.update.sqlpp               |   19 -
 .../multiply_int16/multiply_int16.3.query.sqlpp |   23 -
 .../multiply_int32/multiply_int32.1.ddl.sqlpp   |   22 -
 .../multiply_int32/multiply_int32.1.query.sqlpp |   20 +
 .../multiply_int32.2.update.sqlpp               |   19 -
 .../multiply_int32/multiply_int32.3.query.sqlpp |   23 -
 .../multiply_int64/multiply_int64.1.ddl.sqlpp   |   22 -
 .../multiply_int64/multiply_int64.1.query.sqlpp |   21 +
 .../multiply_int64.2.update.sqlpp               |   19 -
 .../multiply_int64/multiply_int64.3.query.sqlpp |   23 -
 .../multiply_int8/multiply_int8.1.ddl.sqlpp     |   22 -
 .../multiply_int8/multiply_int8.1.query.sqlpp   |   21 +
 .../multiply_int8/multiply_int8.2.update.sqlpp  |   19 -
 .../multiply_int8/multiply_int8.3.query.sqlpp   |   23 -
 .../subtract_double/subtract_double.1.ddl.sqlpp |   22 -
 .../subtract_double.1.query.sqlpp               |   21 +
 .../subtract_double.2.update.sqlpp              |   19 -
 .../subtract_double.3.query.sqlpp               |   23 -
 .../subtract_float/subtract_float.1.ddl.sqlpp   |   22 -
 .../subtract_float/subtract_float.1.query.sqlpp |   20 +
 .../subtract_float.2.update.sqlpp               |   19 -
 .../subtract_float/subtract_float.3.query.sqlpp |   23 -
 .../subtract_int16/subtract_int16.1.ddl.sqlpp   |   22 -
 .../subtract_int16/subtract_int16.1.query.sqlpp |   20 +
 .../subtract_int16.2.update.sqlpp               |   19 -
 .../subtract_int16/subtract_int16.3.query.sqlpp |   23 -
 .../subtract_int32/subtract_int32.1.ddl.sqlpp   |   22 -
 .../subtract_int32/subtract_int32.1.query.sqlpp |   21 +
 .../subtract_int32.2.update.sqlpp               |   19 -
 .../subtract_int32/subtract_int32.3.query.sqlpp |   23 -
 .../subtract_int64/subtract_int64.1.ddl.sqlpp   |   22 -
 .../subtract_int64/subtract_int64.1.query.sqlpp |   20 +
 .../subtract_int64.2.update.sqlpp               |   19 -
 .../subtract_int64/subtract_int64.3.query.sqlpp |   23 -
 .../subtract_int8/subtract_int8.1.ddl.sqlpp     |   22 -
 .../subtract_int8/subtract_int8.1.query.sqlpp   |   21 +
 .../subtract_int8/subtract_int8.2.update.sqlpp  |   19 -
 .../subtract_int8/subtract_int8.3.query.sqlpp   |   23 -
 .../unary-minus_null.1.ddl.sqlpp                |   22 -
 .../unary-minus_null.1.query.sqlpp              |   20 +
 .../unary-minus_null.2.update.sqlpp             |   19 -
 .../unary-minus_null.3.query.sqlpp              |   23 -
 .../tinysocial-suite.12.query.sqlpp             |    2 +-
 .../tinysocial-suite.13.query.sqlpp             |    2 +-
 .../left-outer-unnest-with-pos.1.query.sqlpp    |   30 +
 .../left-outer-unnest.1.query.sqlpp             |   30 +
 .../results/binary/insert/insert.1.adm          |   70 +-
 .../double_missing/double_missing.1.adm         |    1 +
 .../float_missing/float_missing.1.adm           |    1 +
 .../int16_missing/int16_missing.1.adm           |    1 +
 .../int32_missing/int32_missing.1.adm           |    1 +
 .../int64_missing/int64_missing.1.adm           |    1 +
 .../comparison/int8_missing/int8_missing.1.adm  |    1 +
 .../string_missing/string_missing.1.adm         |    1 +
 .../cross-dataverse/cross-dv02/cross-dv02.1.adm |    8 +-
 .../cross-dataverse/cross-dv04/cross-dv04.1.adm |    8 +-
 .../cross-dataverse/cross-dv19/cross-dv19.1.adm |   14 +-
 .../insert_across_dataverses.1.adm              |    4 +-
 .../custord/customer_q_01/customer_q_01.1.adm   |    4 +-
 .../results/custord/join_q_03/join_q_03.1.adm   |    6 +-
 .../results/custord/order_q_03/order_q_03.1.adm |    8 +-
 .../results/custord/order_q_04/order_q_04.1.adm |    6 +-
 .../create-drop-cltype/create-drop-cltype.1.adm |    2 +-
 .../create-drop-opntype.1.adm                   |    2 +-
 .../insert-src-dst-01/insert-src-dst-01.1.adm   |    8 +-
 .../opentype-c2o-recursive.1.adm                |    6 +-
 .../results/dml/opentype-c2o/opentype-c2o.1.adm |    2 +-
 .../opentype-closed-optional.1.adm              |    2 +-
 .../opentype-noexpand/opentype-noexpand.1.adm   |    2 +-
 .../opentype-o2c-recursive.1.adm                |    6 +-
 .../results/dml/opentype-o2c/opentype-o2c.1.adm |    2 +-
 ...-delete-btree-secondary-index-nullable.1.adm |   22 +-
 ...scan-delete-btree-secondary-index-open.1.adm |   22 +-
 ...-insert-btree-secondary-index-nullable.1.adm |   22 +-
 ...scan-insert-btree-secondary-index-open.1.adm |   22 +-
 .../runtimets/results/employee/q_01/q_01.1.adm  |    8 +-
 .../runtimets/results/employee/q_02/q_02.1.adm  |    6 +-
 .../results/feeds/feeds_01/feeds_01.1.adm       |    2 +-
 .../results/feeds/feeds_03/feeds_03.1.adm       |    2 +-
 .../cust-index-age-nullable.1.adm               |    2 +-
 ...verted-index-olist-edit-distance-panic.1.adm | 1414 +++++++++---------
 .../inverted-index-olist-edit-distance.1.adm    |   10 +-
 .../ngram-edit-distance-inline.1.adm            |   26 +-
 .../ngram-edit-distance.1.adm                   |   26 +-
 .../olist-edit-distance-inline.1.adm            |  300 ++--
 .../olist-edit-distance.1.adm                   |  300 ++--
 .../olist-jaccard-inline.1.adm                  |  224 +--
 .../olist-jaccard/olist-jaccard.1.adm           |  224 +--
 .../ulist-jaccard-inline.1.adm                  |  224 +--
 .../ulist-jaccard/ulist-jaccard.1.adm           |  224 +--
 .../results/json/int01-cleanjson/int01.1.json   |    2 +-
 .../results/leftouterjoin/loj-01/loj-01.1.adm   |  100 ++
 .../type_promotion_0/type_promotion_0.1.adm     |   16 +-
 .../results/misc/flushtest/flushtest.1.adm      | 1154 +++++++-------
 .../query-ASTERIXDB-865.1.adm                   |    2 +-
 .../misc/string_eq_01/string_eq_01.1.adm        |    2 +-
 .../delete-from-loaded-dataset-with-index.1.adm |    2 +-
 .../load-with-index/load-with-index.1.adm       |    8 +-
 .../load-with-ngram-index.1.adm                 |   12 +-
 .../load-with-word-index.1.adm                  |   12 +-
 ...-delete-btree-secondary-index-nullable.1.adm |   22 +-
 ...-insert-btree-secondary-index-nullable.1.adm |   22 +-
 .../ngram-edit-distance-inline.1.adm            |   26 +-
 .../ngram-edit-distance.1.adm                   |   26 +-
 .../cust-index-age-nullable.1.adm               |    2 +-
 ...verted-index-olist-edit-distance-panic.1.adm | 1414 +++++++++---------
 .../inverted-index-olist-edit-distance.1.adm    |   10 +-
 .../ngram-edit-distance-inline.1.adm            |   22 +-
 .../ngram-edit-distance.1.adm                   |   22 +-
 .../nestrecords/nestrecord/nestrecord.1.adm     |    4 +-
 .../null-missing/comparison/comparison.1.adm    |    1 +
 .../open-closed-14/open-closed-14.1.adm         |    8 +-
 .../open-closed-26/open-closed-26.1.adm         |    2 +-
 .../ngram-edit-distance-inline.1.adm            |   22 +-
 .../ngram-edit-distance.1.adm                   |   22 +-
 .../numeric_types_01/numeric_types_01.1.adm     |    2 +-
 .../count-nullable/count-nullable.1.adm         |    2 +-
 .../insert_from_ext_ds/insert_from_ext_ds.1.adm |    8 +-
 .../tinysocial-suite/tinysocial-suite.12.adm    |   14 +-
 .../tinysocial-suite/tinysocial-suite.4.adm     |    2 +-
 .../tinysocial-suite/tinysocial-suite.5.adm     |    4 +-
 .../tinysocial-suite/tinysocial-suite.6.adm     |    4 +-
 .../left-outer-unnest-with-pos.1.adm            |    6 +
 .../left-outer-unnest/left-outer-unnest.1.adm   |    6 +
 .../upsert/nullable-index/nullable-index.1.adm  |    4 +-
 .../user-defined-functions/udf23/udf23.1.adm    |   12 +-
 .../comparison/binary_null/binary_null.1.ast    |   69 +
 .../comparison/double_null/double_null.1.ast    |   69 +
 .../comparison/double_null/double_null.2.ast    |    0
 .../comparison/double_null/double_null.3.ast    |  100 --
 .../comparison/float_null/float_null.1.ast      |   69 +
 .../comparison/float_null/float_null.2.ast      |    0
 .../comparison/float_null/float_null.3.ast      |  100 --
 .../comparison/int16_null/int16_null.1.ast      |   69 +
 .../comparison/int32_null/int32_null.1.ast      |   70 +-
 .../comparison/int32_null/int32_null.2.ast      |    0
 .../comparison/int32_null/int32_null.3.ast      |   99 --
 .../comparison/int64_null/int64_null.1.ast      |   69 +
 .../comparison/int64_null/int64_null.2.ast      |    0
 .../comparison/int64_null/int64_null.3.ast      |  100 --
 .../comparison/int8_null/int8_null.1.ast        |   69 +
 .../comparison/int8_null/int8_null.2.ast        |    0
 .../comparison/int8_null/int8_null.3.ast        |  100 --
 .../comparison/string_null/string_null.1.ast    |   57 +
 .../comparison/string_null/string_null.2.ast    |    0
 .../comparison/string_null/string_null.3.ast    |   88 --
 .../numeric/add_double/add_double.1.ast         |  108 ++
 .../numeric/add_float/add_float.1.ast           |  108 ++
 .../numeric/add_int16/add_int16.1.ast           |  108 ++
 .../numeric/add_int32/add_int32.1.ast           |  108 ++
 .../numeric/add_int64/add_int64.1.ast           |  108 ++
 .../numeric/add_int8/add_int8.1.ast             |  108 ++
 .../numeric/divide_double/divide_double.1.ast   |  107 ++
 .../numeric/divide_float/divide_float.1.ast     |  107 ++
 .../numeric/divide_int16/divide_int16.1.ast     |  107 ++
 .../numeric/divide_int32/divide_int32.1.ast     |  107 ++
 .../numeric/divide_int64/divide_int64.1.ast     |  107 ++
 .../numeric/divide_int8/divide_int8.1.ast       |  107 ++
 .../numeric/multiply_double.ast                 |  103 ++
 .../multiply_double/multiply_double.1.ast       |  103 ++
 .../numeric/multiply_float.ast                  |  104 ++
 .../numeric/multiply_float/multiply_float.1.ast |  103 ++
 .../numeric/multiply_int16.ast                  |  103 ++
 .../numeric/multiply_int16/multiply_int16.1.ast |  103 ++
 .../numeric/multiply_int32.ast                  |  103 ++
 .../numeric/multiply_int32/multiply_int32.1.ast |  103 ++
 .../numeric/multiply_int64.ast                  |  104 ++
 .../numeric/multiply_int64/multiply_int64.1.ast |  103 ++
 .../numeric/multiply_int8.ast                   |  103 ++
 .../numeric/multiply_int8/multiply_int8.1.ast   |  103 ++
 .../subtract_double/subtract_double.1.ast       |  108 ++
 .../numeric/subtract_float/subtract_float.1.ast |  108 ++
 .../numeric/subtract_int16/subtract_int16.1.ast |  108 ++
 .../numeric/subtract_int32/subtract_int32.1.ast |  108 ++
 .../numeric/subtract_int64/subtract_int64.1.ast |  108 ++
 .../numeric/subtract_int8/subtract_int8.1.ast   |  108 ++
 .../unary-minus_null/unary-minus_null.1.ast     |   13 +
 .../tinysocial-suite/tinysocial-suite.12.ast    |    2 +-
 .../tinysocial-suite/tinysocial-suite.13.ast    |    2 +-
 .../resources/runtimets/testsuite_sqlpp.xml     |   62 +-
 .../common/exceptions/TypeException.java        |   43 -
 .../apache/asterix/test/aql/TestExecutor.java   |   12 +-
 .../external/library/java/JObjectUtil.java      |    8 +-
 .../asterix/external/parser/ADMDataParser.java  |   16 +-
 .../external/util/ExternalDataUtils.java        |    2 +-
 .../asterix/external/library/ClassAdParser.java |   10 +-
 .../common/expression/RecordTypeDefinition.java |   27 +-
 .../lang/common/visitor/FormatPrintVisitor.java |    4 +-
 .../lang/common/visitor/QueryPrintVisitor.java  |    4 +-
 .../metadata/bootstrap/MetadataRecordTypes.java |   18 +-
 .../metadata/declared/AqlMetadataProvider.java  |   24 +-
 .../entities/AsterixBuiltinTypeMap.java         |   12 +-
 .../FeedTupleTranslator.java                    |    3 +-
 .../asterix/builders/AbstractListBuilder.java   |   25 +-
 .../apache/asterix/builders/RecordBuilder.java  |   58 +-
 .../data/nontagged/AqlMissingWriterFactory.java |    2 +-
 .../serde/ARecordSerializerDeserializer.java    |   62 +-
 .../pointables/ARecordVisitablePointable.java   |   33 +-
 .../om/pointables/cast/ACastVisitor.java        |   12 +-
 .../asterix/om/pointables/cast/AListCaster.java |   18 +-
 .../om/pointables/cast/ARecordCaster.java       |   44 +-
 .../pointables/nonvisitor/ARecordPointable.java |   29 +-
 .../om/pointables/printer/ARecordPrinter.java   |   46 +-
 .../base/AbstractResultTypeComputer.java        |    8 +-
 .../typecomputer/impl/ABinaryTypeComputer.java  |    4 +-
 .../typecomputer/impl/ABooleanTypeComputer.java |    4 +-
 .../typecomputer/impl/ACircleTypeComputer.java  |    4 +-
 .../impl/ADateTimeTypeComputer.java             |    4 +-
 .../om/typecomputer/impl/ADateTypeComputer.java |    4 +-
 .../impl/ADayTimeDurationTypeComputer.java      |    4 +-
 .../typecomputer/impl/ADoubleTypeComputer.java  |    4 +-
 .../impl/ADurationTypeComputer.java             |    4 +-
 .../typecomputer/impl/AFloatTypeComputer.java   |    4 +-
 .../typecomputer/impl/AInt16TypeComputer.java   |    4 +-
 .../typecomputer/impl/AInt32TypeComputer.java   |    4 +-
 .../typecomputer/impl/AInt64TypeComputer.java   |    4 +-
 .../om/typecomputer/impl/AInt8TypeComputer.java |    4 +-
 .../impl/AIntervalTypeComputer.java             |    4 +-
 .../om/typecomputer/impl/ALineTypeComputer.java |    4 +-
 .../typecomputer/impl/APoint3DTypeComputer.java |    4 +-
 .../typecomputer/impl/APointTypeComputer.java   |    4 +-
 .../typecomputer/impl/APolygonTypeComputer.java |    4 +-
 .../impl/ARectangleTypeComputer.java            |    4 +-
 .../typecomputer/impl/AStringTypeComputer.java  |    4 +-
 .../om/typecomputer/impl/ATimeTypeComputer.java |    4 +-
 .../om/typecomputer/impl/AUUIDTypeComputer.java |    4 +-
 .../impl/AYearMonthDurationTypeComputer.java    |    4 +-
 .../impl/AbstractStringTypeComputer.java        |    4 +-
 .../impl/BooleanFunctionTypeComputer.java       |    2 +-
 .../impl/ClosedRecordConstructorResultType.java |    8 +-
 .../impl/CollectionMemberResultType.java        |    3 +-
 .../impl/CollectionToSequenceTypeComputer.java  |    4 +-
 .../impl/ConcatNonNullTypeComputer.java         |    4 +-
 .../impl/FieldAccessByIndexResultType.java      |   42 +-
 .../impl/FieldAccessByNameResultType.java       |   76 +-
 .../impl/FieldAccessNestedResultType.java       |   69 +-
 .../GetOverlappingInvervalTypeComputer.java     |    4 +-
 .../impl/MinMaxAggTypeComputer.java             |    5 +-
 .../impl/NonTaggedGetItemResultType.java        |    3 +-
 .../impl/NumericAddSubMulDivTypeComputer.java   |    4 +-
 .../impl/NumericAggTypeComputer.java            |    7 +-
 .../NumericRoundHalfToEven2TypeComputer.java    |    3 +-
 .../impl/NumericUnaryFunctionTypeComputer.java  |    3 +-
 .../impl/OrderedListOfAInt32TypeComputer.java   |    4 +-
 .../impl/OrderedListOfAInt64TypeComputer.java   |    4 +-
 .../OrderedListOfAIntervalTypeComputer.java     |    4 +-
 .../impl/OrderedListOfAPointTypeComputer.java   |    4 +-
 .../impl/OrderedListOfAStringTypeComputer.java  |    4 +-
 .../impl/OrderedListOfAnyTypeComputer.java      |    4 +-
 .../impl/RecordAddFieldsTypeComputer.java       |    6 +-
 .../impl/RecordMergeTypeComputer.java           |    6 +-
 .../impl/RecordRemoveFieldsTypeComputer.java    |   25 +-
 .../ScalarVersionOfAggregateResultType.java     |    5 +-
 .../impl/StringBooleanTypeComputer.java         |    4 +-
 .../impl/StringStringTypeComputer.java          |    4 +-
 .../impl/Substring2TypeComputer.java            |    3 +-
 .../impl/SubstringTypeComputer.java             |    3 +-
 .../om/typecomputer/impl/TypeComputeUtils.java  |    8 +-
 .../impl/UnaryBinaryInt64TypeComputer.java      |    3 +-
 .../impl/UnaryMinusTypeComputer.java            |    3 +-
 .../impl/UnaryStringInt64TypeComputer.java      |    3 +-
 .../apache/asterix/om/types/ARecordType.java    |    2 +-
 .../org/apache/asterix/om/types/AUnionType.java |   16 +-
 .../asterix/om/util/NonTaggedFormatUtil.java    |    4 +-
 .../ClosedRecordConstructorEvalFactory.java     |    7 -
 .../OpenRecordConstructorDescriptor.java        |   13 +-
 .../functions/CastRecordDescriptor.java         |    4 +-
 .../records/FieldAccessByIndexEvalFactory.java  |   17 +-
 .../records/FieldAccessNestedEvalFactory.java   |    7 +
 .../std/ScanCollectionDescriptor.java           |    1 +
 .../testframework/context/TestCaseContext.java  |    6 +-
 .../core/algebra/base/LogicalOperatorTag.java   |    2 +-
 .../core/algebra/base/PhysicalOperatorTag.java  |    1 +
 .../logical/AbstractUnnestNonMapOperator.java   |   18 +-
 .../operators/logical/AssignOperator.java       |    2 +-
 .../logical/LeftOuterJoinOperator.java          |    2 +-
 .../logical/LeftOuterUnnestMapOperator.java     |    2 +-
 .../logical/LeftOuterUnnestOperator.java        |   73 +
 .../operators/logical/OuterUnnestOperator.java  |   71 -
 .../operators/logical/SelectOperator.java       |    4 +-
 .../visitors/CardinalityInferenceVisitor.java   |    4 +-
 .../visitors/FDsAndEquivClassesVisitor.java     |    5 +-
 .../visitors/IsomorphismOperatorVisitor.java    |   21 +-
 .../IsomorphismVariableMappingVisitor.java      |   37 +-
 ...OperatorDeepCopyWithNewVariablesVisitor.java |    8 +-
 .../visitors/LogicalPropertiesVisitor.java      |    5 +-
 .../visitors/OperatorDeepCopyVisitor.java       |   11 +-
 .../visitors/PrimaryKeyVariablesVisitor.java    |    5 +-
 .../visitors/ProducedVariableVisitor.java       |    4 +-
 .../logical/visitors/SchemaVariableVisitor.java |    4 +-
 .../visitors/SubstituteVariableVisitor.java     |    4 +-
 .../logical/visitors/UsedVariableVisitor.java   |    4 +-
 .../physical/AbstractUnnestPOperator.java       |   89 ++
 .../physical/HybridHashJoinPOperator.java       |    4 +-
 .../physical/InMemoryHashJoinPOperator.java     |   22 +-
 .../physical/LeftOuterUnnestPOperator.java      |   34 +
 .../operators/physical/NLJoinPOperator.java     |    8 +-
 .../physical/StreamSelectPOperator.java         |    9 +-
 .../operators/physical/SubplanPOperator.java    |   14 +-
 .../operators/physical/UnnestPOperator.java     |   77 +-
 .../LogicalOperatorPrettyPrintVisitor.java      |    4 +-
 .../typing/PropagatingTypeEnvironment.java      |    2 +-
 .../visitors/ILogicalOperatorVisitor.java       |    4 +-
 .../core/jobgen/impl/JobGenContext.java         |    2 +-
 .../rules/BreakSelectIntoConjunctsRule.java     |    2 +-
 .../rewriter/rules/PushSelectIntoJoinRule.java  |    4 +-
 .../SetAlgebricksPhysicalOperatorsRule.java     |    4 +
 ...placeNtsWithSubplanInputOperatorVisitor.java |    5 +-
 .../operators/std/UnnestRuntimeFactory.java     |  155 +-
 .../tests/pushruntime/PushRuntimeTest.java      |  128 +-
 586 files changed, 10776 insertions(+), 9243 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/b0fe0ac0/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/InvertedIndexPOperator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/InvertedIndexPOperator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/InvertedIndexPOperator.java
index fe364fa..4e1d9b0 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/InvertedIndexPOperator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/InvertedIndexPOperator.java
@@ -154,7 +154,7 @@ public class InvertedIndexPOperator extends IndexSearchPOperator {
 
     public Pair<IOperatorDescriptor, AlgebricksPartitionConstraint> buildInvertedIndexRuntime(
             AqlMetadataProvider metadataProvider, JobGenContext context, JobSpecification jobSpec,
-            AbstractUnnestMapOperator unnestMap, IOperatorSchema opSchema, boolean retainInput, boolean retainNull,
+            AbstractUnnestMapOperator unnestMap, IOperatorSchema opSchema, boolean retainInput, boolean retainMissing,
             String datasetName, Dataset dataset, String indexName, ATypeTag searchKeyType, int[] keyFields,
             SearchModifierType searchModifierType, IAlgebricksConstantValue similarityThreshold,
             int[] minFilterFieldIndexes, int[] maxFilterFieldIndexes) throws AlgebricksException {
@@ -285,7 +285,7 @@ public class InvertedIndexPOperator extends IndexSearchPOperator {
                     jobSpec, queryField, appContext.getStorageManagerInterface(), secondarySplitsAndConstraint.first,
                     appContext.getIndexLifecycleManagerProvider(), tokenTypeTraits, tokenComparatorFactories,
                     invListsTypeTraits, invListsComparatorFactories, dataflowHelperFactory, queryTokenizerFactory,
-                    searchModifierFactory, outputRecDesc, retainInput, retainNull, context.getNullWriterFactory(),
+                    searchModifierFactory, outputRecDesc, retainInput, retainMissing, context.getMissingWriterFactory(),
                     NoOpOperationCallbackFactory.INSTANCE, minFilterFieldIndexes, maxFilterFieldIndexes);
 
             return new Pair<IOperatorDescriptor, AlgebricksPartitionConstraint>(invIndexSearchOp,

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/b0fe0ac0/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
index 03ea289..53348fb 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
@@ -27,6 +27,7 @@ import org.apache.asterix.optimizer.rules.AsterixExtractFunctionsFromJoinConditi
 import org.apache.asterix.optimizer.rules.AsterixInlineVariablesRule;
 import org.apache.asterix.optimizer.rules.AsterixIntroduceGroupByCombinerRule;
 import org.apache.asterix.optimizer.rules.ByNameToByIndexFieldAccessRule;
+import org.apache.asterix.optimizer.rules.RemoveLeftOuterUnnestForLeftOuterJoinRule;
 import org.apache.asterix.optimizer.rules.CancelUnnestWithNestedListifyRule;
 import org.apache.asterix.optimizer.rules.CheckFilterExpressionTypeRule;
 import org.apache.asterix.optimizer.rules.ConstantFoldingRule;
@@ -124,28 +125,31 @@ import org.apache.hyracks.algebricks.rewriter.rules.subplan.SubplanOutOfGroupRul
 
 public final class RuleCollections {
 
-    public final static List<IAlgebraicRewriteRule> buildInitialTranslationRuleCollection() {
-        List<IAlgebraicRewriteRule> typeInfer = new LinkedList<IAlgebraicRewriteRule>();
+    private RuleCollections() {
+    }
+
+    public static final List<IAlgebraicRewriteRule> buildInitialTranslationRuleCollection() {
+        List<IAlgebraicRewriteRule> typeInfer = new LinkedList<>();
         typeInfer.add(new TranslateIntervalExpressionRule());
         return typeInfer;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildTypeInferenceRuleCollection() {
-        List<IAlgebraicRewriteRule> typeInfer = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildTypeInferenceRuleCollection() {
+        List<IAlgebraicRewriteRule> typeInfer = new LinkedList<>();
         typeInfer.add(new InlineUnnestFunctionRule());
         typeInfer.add(new InferTypesRule());
         typeInfer.add(new CheckFilterExpressionTypeRule());
         return typeInfer;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildAutogenerateIDRuleCollection() {
+    public static final List<IAlgebraicRewriteRule> buildAutogenerateIDRuleCollection() {
         List<IAlgebraicRewriteRule> autogen = new LinkedList<>();
         autogen.add(new IntroduceAutogenerateIDRule());
         return autogen;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildNormalizationRuleCollection() {
-        List<IAlgebraicRewriteRule> normalization = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildNormalizationRuleCollection() {
+        List<IAlgebraicRewriteRule> normalization = new LinkedList<>();
         normalization.add(new IntroduceUnnestForCollectionToSequenceRule());
         normalization.add(new EliminateSubplanRule());
         normalization.add(new EnforceOrderByAfterSubplan());
@@ -173,8 +177,8 @@ public final class RuleCollections {
         return normalization;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildCondPushDownAndJoinInferenceRuleCollection() {
-        List<IAlgebraicRewriteRule> condPushDownAndJoinInference = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildCondPushDownAndJoinInferenceRuleCollection() {
+        List<IAlgebraicRewriteRule> condPushDownAndJoinInference = new LinkedList<>();
 
         condPushDownAndJoinInference.add(new PushSelectDownRule());
         condPushDownAndJoinInference.add(new PushSortDownRule());
@@ -211,8 +215,8 @@ public final class RuleCollections {
         return condPushDownAndJoinInference;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildLoadFieldsRuleCollection() {
-        List<IAlgebraicRewriteRule> fieldLoads = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildLoadFieldsRuleCollection() {
+        List<IAlgebraicRewriteRule> fieldLoads = new LinkedList<>();
         fieldLoads.add(new LoadRecordFieldsRule());
         fieldLoads.add(new PushFieldAccessRule());
         // fieldLoads.add(new ByNameToByHandleFieldAccessRule()); -- disabled
@@ -225,18 +229,19 @@ public final class RuleCollections {
         fieldLoads.add(new FeedScanCollectionToUnnest());
         fieldLoads.add(new NestedSubplanToJoinRule());
         fieldLoads.add(new InlineSubplanInputForNestedTupleSourceRule());
+        fieldLoads.add(new RemoveLeftOuterUnnestForLeftOuterJoinRule());
         return fieldLoads;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildFuzzyJoinRuleCollection() {
-        List<IAlgebraicRewriteRule> fuzzy = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildFuzzyJoinRuleCollection() {
+        List<IAlgebraicRewriteRule> fuzzy = new LinkedList<>();
         // fuzzy.add(new FuzzyJoinRule()); -- The non-indexed fuzzy join will be temporarily disabled. It should be enabled some time in the near future.
         fuzzy.add(new InferTypesRule());
         return fuzzy;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildConsolidationRuleCollection() {
-        List<IAlgebraicRewriteRule> consolidation = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildConsolidationRuleCollection() {
+        List<IAlgebraicRewriteRule> consolidation = new LinkedList<>();
         consolidation.add(new ConsolidateSelectsRule());
         consolidation.add(new ConsolidateAssignsRule());
         consolidation.add(new InlineAssignIntoAggregateRule());
@@ -251,8 +256,8 @@ public final class RuleCollections {
         return consolidation;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildAccessMethodRuleCollection() {
-        List<IAlgebraicRewriteRule> accessMethod = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildAccessMethodRuleCollection() {
+        List<IAlgebraicRewriteRule> accessMethod = new LinkedList<>();
         accessMethod.add(new IntroduceSelectAccessMethodRule());
         accessMethod.add(new IntroduceJoinAccessMethodRule());
         accessMethod.add(new IntroduceLSMComponentFilterRule());
@@ -263,8 +268,8 @@ public final class RuleCollections {
         return accessMethod;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildPlanCleanupRuleCollection() {
-        List<IAlgebraicRewriteRule> planCleanupRules = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildPlanCleanupRuleCollection() {
+        List<IAlgebraicRewriteRule> planCleanupRules = new LinkedList<>();
         planCleanupRules.add(new PushAssignBelowUnionAllRule());
         planCleanupRules.add(new ExtractCommonExpressionsRule());
         planCleanupRules.add(new RemoveRedundantVariablesRule());
@@ -278,17 +283,16 @@ public final class RuleCollections {
         return planCleanupRules;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildDataExchangeRuleCollection() {
-        List<IAlgebraicRewriteRule> dataExchange = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildDataExchangeRuleCollection() {
+        List<IAlgebraicRewriteRule> dataExchange = new LinkedList<>();
         dataExchange.add(new SetExecutionModeRule());
         return dataExchange;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildPhysicalRewritesAllLevelsRuleCollection() {
-        List<IAlgebraicRewriteRule> physicalRewritesAllLevels = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildPhysicalRewritesAllLevelsRuleCollection() {
+        List<IAlgebraicRewriteRule> physicalRewritesAllLevels = new LinkedList<>();
         physicalRewritesAllLevels.add(new PullSelectOutOfEqJoin());
         //Turned off the following rule for now not to change OptimizerTest results.
-        //physicalRewritesAllLevels.add(new IntroduceTransactionCommitByAssignOpRule());
         physicalRewritesAllLevels.add(new ReplaceSinkOpWithCommitOpRule());
         physicalRewritesAllLevels.add(new SetAlgebricksPhysicalOperatorsRule());
         physicalRewritesAllLevels.add(new SetAsterixPhysicalOperatorsRule());
@@ -307,8 +311,8 @@ public final class RuleCollections {
         return physicalRewritesAllLevels;
     }
 
-    public final static List<IAlgebraicRewriteRule> buildPhysicalRewritesTopLevelRuleCollection() {
-        List<IAlgebraicRewriteRule> physicalRewritesTopLevel = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> buildPhysicalRewritesTopLevelRuleCollection() {
+        List<IAlgebraicRewriteRule> physicalRewritesTopLevel = new LinkedList<>();
         physicalRewritesTopLevel.add(new PushNestedOrderByUnderPreSortedGroupByRule());
         physicalRewritesTopLevel.add(new CopyLimitDownRule());
         // CopyLimitDownRule may generates non-topmost limits with numeric_adds functions.
@@ -323,8 +327,8 @@ public final class RuleCollections {
         return physicalRewritesTopLevel;
     }
 
-    public final static List<IAlgebraicRewriteRule> prepareForJobGenRuleCollection() {
-        List<IAlgebraicRewriteRule> prepareForJobGenRewrites = new LinkedList<IAlgebraicRewriteRule>();
+    public static final List<IAlgebraicRewriteRule> prepareForJobGenRuleCollection() {
+        List<IAlgebraicRewriteRule> prepareForJobGenRewrites = new LinkedList<>();
         prepareForJobGenRewrites
                 .add(new IsolateHyracksOperatorsRule(HeuristicOptimizer.hyraxOperatorsBelowWhichJobGenIsDisabled));
         prepareForJobGenRewrites.add(new ExtractCommonOperatorsRule());

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/b0fe0ac0/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
index b4f8ac3..6e8bd69 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
@@ -20,7 +20,7 @@
 package org.apache.asterix.optimizer.rules;
 
 import java.util.ArrayList;
-import java.util.List;
+import java.util.Collections;
 
 import org.apache.asterix.algebra.base.AsterixOperatorAnnotations;
 import org.apache.asterix.lang.common.util.FunctionUtil;
@@ -36,19 +36,16 @@ import org.apache.asterix.om.types.IAType;
 import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.commons.lang3.mutable.MutableObject;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.exceptions.NotImplementedException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
 import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
 import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
 import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 
@@ -63,79 +60,84 @@ public class ByNameToByIndexFieldAccessRule implements IAlgebraicRewriteRule {
     @Override
     public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
             throws AlgebricksException {
-        AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
-        if (op.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
-            return false;
+        ILogicalOperator op = opRef.getValue();
+        if (op.acceptExpressionTransform(exprRef -> rewriteExpressionReference(op, exprRef, context))) {
+            op.removeAnnotation(AsterixOperatorAnnotations.PUSHED_FIELD_ACCESS);
+            context.computeAndSetTypeEnvironmentForOperator(op);
+            return true;
         }
-        AssignOperator assign = (AssignOperator) op;
-        if (assign.getExpressions().get(0).getValue().getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+        return false;
+    }
+
+    // Recursively rewrites expression reference.
+    private boolean rewriteExpressionReference(ILogicalOperator op, Mutable<ILogicalExpression> exprRef,
+            IOptimizationContext context) throws AlgebricksException {
+        ILogicalExpression expr = exprRef.getValue();
+        if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
             return false;
         }
-
-        List<Mutable<ILogicalExpression>> expressions = assign.getExpressions();
         boolean changed = false;
-        for (int i = 0; i < expressions.size(); i++) {
-            AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) expressions.get(i).getValue();
-            if (fce.getFunctionIdentifier() != AsterixBuiltinFunctions.FIELD_ACCESS_BY_NAME) {
-                continue;
-            }
-            IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op);
-
-            ILogicalExpression a0 = fce.getArguments().get(0).getValue();
-            if (a0.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
-                LogicalVariable var1 = context.newVar();
-                ArrayList<LogicalVariable> varArray = new ArrayList<>(1);
-                varArray.add(var1);
-                ArrayList<Mutable<ILogicalExpression>> exprArray = new ArrayList<>(1);
-                exprArray.add(new MutableObject<ILogicalExpression>(a0));
-                AssignOperator assignVar = new AssignOperator(varArray, exprArray);
-                fce.getArguments().get(0).setValue(new VariableReferenceExpression(var1));
-                assignVar.getInputs().add(new MutableObject<ILogicalOperator>(assign.getInputs().get(0).getValue()));
-                assign.getInputs().get(0).setValue(assignVar);
-                context.computeAndSetTypeEnvironmentForOperator(assignVar);
-                context.computeAndSetTypeEnvironmentForOperator(assign);
-                //access by name was not replaced to access by index, but the plan was altered, hence changed is true
+        AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
+        for (Mutable<ILogicalExpression> funcArgRef : funcExpr.getArguments()) {
+            if (rewriteExpressionReference(op, funcArgRef, context)) {
                 changed = true;
             }
+        }
+        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) expr;
+        if (fce.getFunctionIdentifier() != AsterixBuiltinFunctions.FIELD_ACCESS_BY_NAME) {
+            return changed;
+        }
+        changed |= extractFirstArg(fce, op, context);
+        IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op);
+        IAType t = (IAType) env.getType(fce.getArguments().get(0).getValue());
+        changed |= rewriteFieldAccess(exprRef, fce, getActualType(t));
+        return changed;
+    }
 
-            IAType t = (IAType) env.getType(fce.getArguments().get(0).getValue());
-            switch (t.getTypeTag()) {
-                case ANY:
-                    return changed;
-                case RECORD:
-                    ARecordType recType = (ARecordType) t;
-                    ILogicalExpression fai = createFieldAccessByIndex(recType, fce);
-                    if (fai == null) {
-                        return changed;
-                    }
-                    expressions.get(i).setValue(fai);
-                    changed = true;
-                    break;
-                case UNION:
-                    AUnionType unionT = (AUnionType) t;
-                    if (!unionT.isUnknownableType()) {
-                        throw new NotImplementedException("Union " + unionT);
-                    }
-                    IAType t2 = unionT.getActualType();
-                    if (t2.getTypeTag() != ATypeTag.RECORD) {
-                        throw new AlgebricksException("Cannot call field-access on data of type " + t);
-                    }
-                    recType = (ARecordType) t2;
-                    fai = createFieldAccessByIndex(recType, fce);
-                    if (fai == null) {
-                        return changed;
-                    }
-                    expressions.get(i).setValue(fai);
-                    changed = true;
-                    break;
-                default:
-                    throw new AlgebricksException("Cannot call field-access on data of type " + t);
-            }
+    // Extracts the first argument of a field-access expression into an separate assign operator.
+    private boolean extractFirstArg(AbstractFunctionCallExpression fce, ILogicalOperator op,
+            IOptimizationContext context) throws AlgebricksException {
+        ILogicalExpression firstArg = fce.getArguments().get(0).getValue();
+        if (firstArg.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+            return false;
+        }
+        LogicalVariable var1 = context.newVar();
+        AssignOperator assignOp = new AssignOperator(new ArrayList<>(Collections.singletonList(var1)),
+                new ArrayList<>(Collections.singletonList(new MutableObject<>(firstArg))));
+        fce.getArguments().get(0).setValue(new VariableReferenceExpression(var1));
+        assignOp.getInputs().add(new MutableObject<>(op.getInputs().get(0).getValue()));
+        op.getInputs().get(0).setValue(assignOp);
+        context.computeAndSetTypeEnvironmentForOperator(assignOp);
+        return true;
+    }
+
+    // Rewrites field-access-by-name into field-access-by-index if possible.
+    private boolean rewriteFieldAccess(Mutable<ILogicalExpression> exprRef, AbstractFunctionCallExpression fce,
+            IAType t) throws AlgebricksException {
+        if (t.getTypeTag() != ATypeTag.RECORD) {
+            return false;
+        }
+        ILogicalExpression fai = createFieldAccessByIndex((ARecordType) t, fce);
+        boolean changed = fai != null;
+        if (changed) {
+            exprRef.setValue(fai);
         }
-        assign.removeAnnotation(AsterixOperatorAnnotations.PUSHED_FIELD_ACCESS);
         return changed;
     }
 
+    // Gets the actual type of a given type.
+    private IAType getActualType(IAType t) throws AlgebricksException {
+        switch (t.getTypeTag()) {
+            case ANY:
+            case RECORD:
+                return t;
+            case UNION:
+                return ((AUnionType) t).getActualType();
+            default:
+                throw new AlgebricksException("Cannot call field-access on data of type " + t);
+        }
+    }
+
     @SuppressWarnings("unchecked")
     private static ILogicalExpression createFieldAccessByIndex(ARecordType recType,
             AbstractFunctionCallExpression fce) {

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/b0fe0ac0/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
index a58da0d..e692678 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
@@ -95,7 +95,6 @@ public class IntroduceDynamicTypeCastRule implements IAlgebraicRewriteRule {
                  * pattern match: sink insert assign
                  * resulting plan: sink-insert-project-assign
                  */
-
                 AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
                 if (op2.getOperatorTag() == LogicalOperatorTag.INSERT_DELETE_UPSERT) {
                     InsertDeleteUpsertOperator insertDeleteOp = (InsertDeleteUpsertOperator) op2;
@@ -113,7 +112,7 @@ public class IntroduceDynamicTypeCastRule implements IAlgebraicRewriteRule {
 
                     // Derive the Variable which we will potentially wrap with cast/null functions
                     ILogicalExpression expr = insertDeleteOperator.getPayloadExpression().getValue();
-                    List<LogicalVariable> payloadVars = new ArrayList<LogicalVariable>();
+                    List<LogicalVariable> payloadVars = new ArrayList<>();
                     expr.getUsedVariables(payloadVars);
                     recordVar = payloadVars.get(0);
                 } else {
@@ -140,14 +139,13 @@ public class IntroduceDynamicTypeCastRule implements IAlgebraicRewriteRule {
                             "output-record-type defined for expression with multiple input operators");
                 }
                 AbstractLogicalOperator input = (AbstractLogicalOperator) op.getInputs().get(0).getValue();
-                List<LogicalVariable> liveVars = new ArrayList<LogicalVariable>();
+                List<LogicalVariable> liveVars = new ArrayList<>();
                 VariableUtilities.getLiveVariables(input, liveVars);
                 if (liveVars.size() > 1) {
                     throw new AlgebricksException(
                             "Expression with multiple fields cannot be cast to output-record-type!");
                 }
                 recordVar = liveVars.get(0);
-
                 break;
             }
             default: {

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/b0fe0ac0/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
index 0a7d196..6205962 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
@@ -594,18 +594,18 @@ public class IntroduceSecondaryIndexInsertDeleteRule implements IAlgebraicRewrit
                     // create the smallest record
                     enforcedType = new ARecordType(splits.get(splits.size() - 2),
                             new String[] { splits.get(splits.size() - 1) },
-                            new IAType[] { AUnionType.createNullableType(index.getKeyFieldTypes().get(i)) }, true);
+                            new IAType[] { AUnionType.createUnknownableType(index.getKeyFieldTypes().get(i)) }, true);
                     // create the open part of the nested field
                     for (int k = splits.size() - 3; k > (j - 2); k--) {
                         enforcedType = new ARecordType(splits.get(k), new String[] { splits.get(k + 1) },
-                                new IAType[] { AUnionType.createNullableType(enforcedType) }, true);
+                                new IAType[] { AUnionType.createUnknownableType(enforcedType) }, true);
                     }
                     // Bridge the gap
                     Pair<ARecordType, String> gapPair = nestedTypeStack.pop();
                     ARecordType parent = gapPair.first;
 
                     IAType[] parentFieldTypes = ArrayUtils.addAll(parent.getFieldTypes().clone(),
-                            new IAType[] { AUnionType.createNullableType(enforcedType) });
+                            new IAType[] { AUnionType.createUnknownableType(enforcedType) });
                     enforcedType = new ARecordType(bridgeName,
                             ArrayUtils.addAll(parent.getFieldNames(), enforcedType.getTypeName()), parentFieldTypes,
                             true);
@@ -630,7 +630,7 @@ public class IntroduceSecondaryIndexInsertDeleteRule implements IAlgebraicRewrit
                     }
                     if (enforcedFieldType == null) {
                         recordNameTypesMap.put(splits.get(splits.size() - 1),
-                                AUnionType.createNullableType(index.getKeyFieldTypes().get(i)));
+                                AUnionType.createUnknownableType(index.getKeyFieldTypes().get(i)));
                     }
                     enforcedType = new ARecordType(nestedFieldType.getTypeName(),
                             recordNameTypesMap.keySet().toArray(new String[recordNameTypesMap.size()]),

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/b0fe0ac0/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java
index 9039097..36e93c4 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/LoadRecordFieldsRule.java
@@ -24,14 +24,14 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-
 import org.apache.asterix.algebra.base.AsterixOperatorAnnotations;
+import org.apache.asterix.om.base.AInt32;
 import org.apache.asterix.om.base.AString;
 import org.apache.asterix.om.constants.AsterixConstantValue;
 import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
 import org.apache.asterix.optimizer.base.AnalysisUtil;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
@@ -214,8 +214,8 @@ public class LoadRecordFieldsRule implements IAlgebraicRewriteRule {
                         }
                     }
                 }
-                throw new AlgebricksException("Field access " + getFirstExpr(a2)
-                        + " does not correspond to any input of operator " + topOp);
+                throw new AlgebricksException(
+                        "Field access " + getFirstExpr(a2) + " does not correspond to any input of operator " + topOp);
             }
         }
     }
@@ -242,8 +242,6 @@ public class LoadRecordFieldsRule implements IAlgebraicRewriteRule {
      * into
      * assign $x := Expr
      * assign $y := record-constructor { "field": Expr, ... }
-     *
-     * @param toPush
      */
     private static boolean findAndEliminateRedundantFieldAccess(AssignOperator assign) throws AlgebricksException {
         ILogicalExpression expr = getFirstExpr(assign);
@@ -259,84 +257,66 @@ public class LoadRecordFieldsRule implements IAlgebraicRewriteRule {
             return false;
         }
         ConstantExpression ce = (ConstantExpression) arg1;
+        ILogicalExpression fldExpr;
         if (f.getFunctionIdentifier().equals(AsterixBuiltinFunctions.FIELD_ACCESS_BY_NAME)) {
             String fldName = ((AString) ((AsterixConstantValue) ce.getValue()).getObject()).getStringValue();
-            ILogicalExpression fldExpr = findFieldExpression(assign, recordVar, fldName);
-
-            if (fldExpr != null) {
-                // check the liveness of the new expression
-                List<LogicalVariable> usedVariables = new ArrayList<LogicalVariable>();
-                fldExpr.getUsedVariables(usedVariables);
-                List<LogicalVariable> liveInputVars = new ArrayList<LogicalVariable>();
-                VariableUtilities.getLiveVariables(assign, liveInputVars);
-                usedVariables.removeAll(liveInputVars);
-                if (usedVariables.size() == 0) {
-                    assign.getExpressions().get(0).setValue(fldExpr);
-                    return true;
-                } else {
-                    return false;
-                }
-            } else {
-                return false;
-            }
+            fldExpr = findFieldExpression(assign, recordVar, fldName,
+                    LoadRecordFieldsRule::findFieldByNameFromRecordConstructor);
         } else if (f.getFunctionIdentifier().equals(AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX)) {
-            // int fldIdx = ((IntegerLiteral) ce.getValue()).getValue();
-            // TODO
-            return false;
+            Integer fldIdx = ((AInt32) ((AsterixConstantValue) ce.getValue()).getObject()).getIntegerValue();
+            fldExpr = findFieldExpression(assign, recordVar, fldIdx,
+                    LoadRecordFieldsRule::findFieldByIndexFromRecordConstructor);
         } else if (f.getFunctionIdentifier().equals(AsterixBuiltinFunctions.FIELD_ACCESS_NESTED)) {
             return false;
         } else {
             throw new IllegalStateException();
         }
+
+        if (fldExpr == null) {
+            return false;
+        }
+        // check the liveness of the new expression
+        List<LogicalVariable> usedVariables = new ArrayList<>();
+        fldExpr.getUsedVariables(usedVariables);
+        List<LogicalVariable> liveInputVars = new ArrayList<>();
+        VariableUtilities.getLiveVariables(assign, liveInputVars);
+        usedVariables.removeAll(liveInputVars);
+        if (usedVariables.isEmpty()) {
+            assign.getExpressions().get(0).setValue(fldExpr);
+            return true;
+        } else {
+            return false;
+        }
     }
 
+    @FunctionalInterface
+    private interface FieldResolver {
+        public ILogicalExpression resolve(Object accessKey, AbstractFunctionCallExpression funcExpr);
+    }
+
+    // Finds a field expression.
     private static ILogicalExpression findFieldExpression(AbstractLogicalOperator op, LogicalVariable recordVar,
-            String fldName) {
+            Object accessKey, FieldResolver resolver) {
         for (Mutable<ILogicalOperator> child : op.getInputs()) {
             AbstractLogicalOperator opChild = (AbstractLogicalOperator) child.getValue();
             if (opChild.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
                 AssignOperator op2 = (AssignOperator) opChild;
-                int i = 0;
-                for (LogicalVariable var : op2.getVariables()) {
-                    if (var == recordVar) {
-                        AbstractLogicalExpression constr = (AbstractLogicalExpression) op2.getExpressions().get(i)
-                                .getValue();
-                        if (constr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
-                            return null;
-                        }
-                        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) constr;
-                        if (!fce.getFunctionIdentifier().equals(AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR)
-                                && !fce.getFunctionIdentifier().equals(
-                                        AsterixBuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR)) {
-                            return null;
-                        }
-                        Iterator<Mutable<ILogicalExpression>> fldIter = fce.getArguments().iterator();
-                        while (fldIter.hasNext()) {
-                            ILogicalExpression fldExpr = fldIter.next().getValue();
-                            if (fldExpr.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
-                                ConstantExpression ce = (ConstantExpression) fldExpr;
-                                String f2 = ((AString) ((AsterixConstantValue) ce.getValue()).getObject())
-                                        .getStringValue();
-                                if (fldName.equals(f2)) {
-                                    return fldIter.next().getValue();
-                                }
-                            }
-                            fldIter.next();
-                        }
-                        return null;
-                    }
-                    i++;
+                int i = op2.getVariables().indexOf(recordVar);
+                if (i >= 0) {
+                    AbstractLogicalExpression constr = (AbstractLogicalExpression) op2.getExpressions().get(i)
+                            .getValue();
+                    return resolveFieldExpression(constr, accessKey, resolver);
                 }
             } else if (opChild.getOperatorTag() == LogicalOperatorTag.NESTEDTUPLESOURCE) {
                 NestedTupleSourceOperator nts = (NestedTupleSourceOperator) opChild;
                 AbstractLogicalOperator opBelowNestedPlan = (AbstractLogicalOperator) nts.getDataSourceReference()
                         .getValue().getInputs().get(0).getValue();
-                ILogicalExpression expr1 = findFieldExpression(opBelowNestedPlan, recordVar, fldName);
+                ILogicalExpression expr1 = findFieldExpression(opBelowNestedPlan, recordVar, accessKey, resolver);
                 if (expr1 != null) {
                     return expr1;
                 }
             }
-            ILogicalExpression expr2 = findFieldExpression(opChild, recordVar, fldName);
+            ILogicalExpression expr2 = findFieldExpression(opChild, recordVar, accessKey, resolver);
             if (expr2 != null) {
                 return expr2;
             }
@@ -344,6 +324,45 @@ public class LoadRecordFieldsRule implements IAlgebraicRewriteRule {
         return null;
     }
 
+    // Resolves field expression from an access key and a field resolver.
+    private static ILogicalExpression resolveFieldExpression(AbstractLogicalExpression constr, Object accessKey,
+            FieldResolver resolver) {
+        if (constr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+            return null;
+        }
+        AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) constr;
+        if (!fce.getFunctionIdentifier().equals(AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR)
+                && !fce.getFunctionIdentifier().equals(AsterixBuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR)) {
+            return null;
+        }
+        return resolver.resolve(accessKey, fce);
+    }
+
+    // Resolves field expression by name-based access.
+    private static ILogicalExpression findFieldByNameFromRecordConstructor(Object fldName,
+            AbstractFunctionCallExpression fce) {
+        Iterator<Mutable<ILogicalExpression>> fldIter = fce.getArguments().iterator();
+        while (fldIter.hasNext()) {
+            ILogicalExpression fldExpr = fldIter.next().getValue();
+            if (fldExpr.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
+                ConstantExpression ce = (ConstantExpression) fldExpr;
+                String f2 = ((AString) ((AsterixConstantValue) ce.getValue()).getObject()).getStringValue();
+                if (fldName.equals(f2)) {
+                    return fldIter.next().getValue();
+                }
+            }
+            fldIter.next();
+        }
+        return null;
+    }
+
+    // Resolves field expression by index-based access.
+    private static ILogicalExpression findFieldByIndexFromRecordConstructor(Object index,
+            AbstractFunctionCallExpression fce) {
+        Integer fieldIndex = (Integer) index;
+        return fce.getArguments().size() > fieldIndex ? fce.getArguments().get(2 * fieldIndex + 1).getValue() : null;
+    }
+
     private final class ExtractFieldLoadExpressionVisitor implements ILogicalExpressionReferenceTransform {
 
         private AbstractLogicalOperator topOp;


Mime
View raw message