HAWQ-404. Close each partition after inserting when optimizer guarantees input 
is sorted on partition-id.


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

Branch: refs/heads/master
Commit: 6e6890ae7886b050aeb9c9d7e885fc84eb99937c
Parents: 2c38b42
Author: George Caragea <gcara...@pivotal.io>
Authored: Mon Feb 29 22:21:13 2016 -0800
Committer: Haisheng Yuan <hy...@pivotal.io>
Committed: Wed Mar 2 18:27:22 2016 -0800

----------------------------------------------------------------------
 src/backend/executor/execDML.c              |  99 +++++++++++-------
 src/backend/executor/execMain.c             |  13 +--
 src/backend/executor/execUtils.c            |   2 +-
 src/backend/executor/nodeDML.c              |   2 +-
 src/backend/utils/misc/guc.c                |   2 +-
 src/include/executor/execDML.h              |   3 +-
 src/include/nodes/execnodes.h               |   7 +-
 src/test/regress/expected/goh_partition.out | 126 +++++++++++++++++++++++
 src/test/regress/sql/goh_partition.sql      |  68 ++++++++++++
 9 files changed, 271 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/6e6890ae/src/backend/executor/execDML.c
----------------------------------------------------------------------
diff --git a/src/backend/executor/execDML.c b/src/backend/executor/execDML.c
index d36e9ed..d6f05de 100644
--- a/src/backend/executor/execDML.c
+++ b/src/backend/executor/execDML.c
@@ -158,10 +158,11 @@ reconstructMatchingTupleSlot(TupleTableSlot *slot, 
ResultRelInfo *resultRelInfo)
  */
 void
 ExecInsert(TupleTableSlot *slot,
-                  DestReceiver *dest,
-                  EState *estate,
-                  PlanGenerator planGen,
-                  bool isUpdate)
+               DestReceiver *dest,
+               EState *estate,
+               PlanGenerator planGen,
+               bool isUpdate,
+               bool isInputSorted)
 {
        void            *tuple = NULL;
        ResultRelInfo *resultRelInfo = NULL;
@@ -184,7 +185,7 @@ ExecInsert(TupleTableSlot *slot,
                resultRelInfo = slot_get_partition(slot, estate);
                estate->es_result_relation_info = resultRelInfo;
 
-               if (NULL != resultRelInfo->ri_parquetSendBack)
+               if (NULL != resultRelInfo->ri_insertSendBack)
                {
                        /*
                         * The Parquet part we are about to insert into
@@ -203,59 +204,82 @@ ExecInsert(TupleTableSlot *slot,
                 * inserted into (GPSQL-2291).
                 */
                Oid new_part_oid = resultRelInfo->ri_RelationDesc->rd_id;
-               if (gp_parquet_insert_sort &&
+
+               if (isInputSorted &&
                                PLANGEN_OPTIMIZER == planGen &&
-                               InvalidOid != estate->es_last_parq_part &&
-                               new_part_oid != estate->es_last_parq_part)
+                               InvalidOid != estate->es_last_inserted_part &&
+                               new_part_oid != estate->es_last_inserted_part)
                {
 
                        Assert(NULL != 
estate->es_partition_state->result_partition_hash);
 
                        ResultPartHashEntry *entry = 
hash_search(estate->es_partition_state->result_partition_hash,
-                                                                       
&estate->es_last_parq_part,
-                                                                       
HASH_FIND,
-                                                                       NULL /* 
found */);
+                                       &estate->es_last_inserted_part,
+                                       HASH_FIND,
+                                       NULL /* found */);
 
                        Assert(NULL != entry);
                        Assert(entry->offset < estate->es_num_result_relations);
 
                        ResultRelInfo *oldResultRelInfo = & 
estate->es_result_relations[entry->offset];
+                       Assert(NULL != oldResultRelInfo);
 
-                       elog(DEBUG1, "Switching from old part oid=%d name=[%s] 
to new part oid=%d name=[%s]",
-                                       estate->es_last_parq_part,
-                                       
oldResultRelInfo->ri_RelationDesc->rd_rel->relname.data,
-                                       new_part_oid,
-                                       
resultRelInfo->ri_RelationDesc->rd_rel->relname.data);
-
-                       /*
-                        * We are opening a new partition, and the last 
partition we
-                        * inserted into was a Parquet part. Let's close the old
-                        * parquet insert descriptor to free the memory before
-                        * opening the new one.
-                        */
-                       ParquetInsertDescData *oldInsertDesc = 
oldResultRelInfo->ri_parquetInsertDesc;
 
                        /*
                         * We need to preserve the "sendback" information that 
needs to be
                         * sent back to the QD process from this part.
                         * Compute it here, and store it for later use.
                         */
-                       QueryContextDispatchingSendBack sendback =
-                                       
CreateQueryContextDispatchingSendBack(1);
+                       QueryContextDispatchingSendBack sendback = 
CreateQueryContextDispatchingSendBack(1);
                        sendback->relid = 
RelationGetRelid(oldResultRelInfo->ri_RelationDesc);
-                       oldInsertDesc->sendback = sendback;
-                       parquet_insert_finish(oldInsertDesc);
 
-                       /* Store the sendback information in the resultRelInfo 
for this part */
-                       oldResultRelInfo->ri_parquetSendBack = sendback;
+                       Relation oldRelation = 
oldResultRelInfo->ri_RelationDesc;
+                       if (RelationIsAoRows(oldRelation))
+                       {
+                               AppendOnlyInsertDescData *oldInsertDesc = 
oldResultRelInfo->ri_aoInsertDesc;
+                               Assert(NULL != oldInsertDesc);
+
+                               elog(DEBUG1, "AO: Switching from old part 
oid=%d name=[%s] to new part oid=%d name=[%s]",
+                                               estate->es_last_inserted_part,
+                                               
oldResultRelInfo->ri_RelationDesc->rd_rel->relname.data,
+                                               new_part_oid,
+                                               
resultRelInfo->ri_RelationDesc->rd_rel->relname.data);
 
-                       /* Record in the resultRelInfo that we closed the 
parquet insert descriptor */
-                       oldResultRelInfo->ri_parquetInsertDesc = NULL;
+                               oldInsertDesc->sendback = sendback;
 
-                       /* Reset the last parquet part Oid, it's now closed */
-                       estate->es_last_parq_part = InvalidOid;
+                               appendonly_insert_finish(oldInsertDesc);
+                               oldResultRelInfo->ri_aoInsertDesc = NULL;
+
+                       }
+                       else if (RelationIsParquet(oldRelation))
+                       {
+                               ParquetInsertDescData *oldInsertDesc = 
oldResultRelInfo->ri_parquetInsertDesc;
+                               Assert(NULL != oldInsertDesc);
+
+                               elog(DEBUG1, "PARQ: Switching from old part 
oid=%d name=[%s] to new part oid=%d name=[%s]",
+                                               estate->es_last_inserted_part,
+                                               
oldResultRelInfo->ri_RelationDesc->rd_rel->relname.data,
+                                               new_part_oid,
+                                               
resultRelInfo->ri_RelationDesc->rd_rel->relname.data);
+
+                               oldInsertDesc->sendback = sendback;
+
+                               parquet_insert_finish(oldInsertDesc);
+                               oldResultRelInfo->ri_parquetInsertDesc = NULL;
+
+                       }
+                       else
+                       {
+                               Assert(false && "Unreachable");
+                       }
+
+                       /* Store the sendback information in the resultRelInfo 
for this part */
+                       oldResultRelInfo->ri_insertSendBack = sendback;
+
+                       estate->es_last_inserted_part = InvalidOid;
                }
-       }
+
+  }
        else
        {
                resultRelInfo = estate->es_result_relation_info;
@@ -362,7 +386,7 @@ ExecInsert(TupleTableSlot *slot,
                        resultRelInfo->ri_aoInsertDesc =
                                appendonly_insert_init(resultRelationDesc,
                                                                           
segfileinfo);
-
+                       estate->es_last_inserted_part = 
resultRelationDesc->rd_id;
                }
 
                appendonly_insert(resultRelInfo->ri_aoInsertDesc, tuple, 
&newId, &aoTupleId);
@@ -391,8 +415,7 @@ ExecInsert(TupleTableSlot *slot,
                         * in estate, so that we can close it when switching to 
a
                         * new partition (GPSQL-2291)
                         */
-                       elog(DEBUG1, "Saving es_last_parq_part. Old=%d, 
new=%d", estate->es_last_parq_part, resultRelationDesc->rd_id);
-                       estate->es_last_parq_part = resultRelationDesc->rd_id;
+                       estate->es_last_inserted_part = 
resultRelationDesc->rd_id;
                }
 
                newId = parquet_insert(resultRelInfo->ri_parquetInsertDesc, 
partslot);

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/6e6890ae/src/backend/executor/execMain.c
----------------------------------------------------------------------
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 1c215b0..6fa5cd2 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -2927,7 +2927,7 @@ ExecEndPlan(PlanState *planstate, EState *estate)
        {
                if (resultRelInfo->ri_aoInsertDesc)
                        ++aocount;
-               if (resultRelInfo->ri_parquetInsertDesc || 
resultRelInfo->ri_parquetSendBack)
+               if (resultRelInfo->ri_parquetInsertDesc || 
resultRelInfo->ri_insertSendBack)
                        ++aocount;
                resultRelInfo++;
        }
@@ -2946,6 +2946,7 @@ ExecEndPlan(PlanState *planstate, EState *estate)
                /* end (flush) the INSERT operation in the access layer */
                if (resultRelInfo->ri_aoInsertDesc)
                {
+
                        sendback = CreateQueryContextDispatchingSendBack(1);
                        resultRelInfo->ri_aoInsertDesc->sendback = sendback;
                        sendback->relid = 
RelationGetRelid(resultRelInfo->ri_RelationDesc);
@@ -2956,9 +2957,9 @@ ExecEndPlan(PlanState *planstate, EState *estate)
                /*need add processing for parquet insert desc*/
                if (resultRelInfo->ri_parquetInsertDesc){
 
-                       AssertImply(resultRelInfo->ri_parquetSendBack, 
gp_parquet_insert_sort);
+                       AssertImply(resultRelInfo->ri_insertSendBack, 
gp_parquet_insert_sort);
 
-                       if (NULL != resultRelInfo->ri_parquetSendBack)
+                       if (NULL != resultRelInfo->ri_insertSendBack)
                        {
                                /*
                                 * The Parquet part we just finished inserting 
into already
@@ -2984,10 +2985,10 @@ ExecEndPlan(PlanState *planstate, EState *estate)
                 * in the resultRelInfo, since the ri_parquetInsertDesc is freed
                 * (GPSQL-2291)
                 */
-               if (NULL != resultRelInfo->ri_parquetSendBack)
+               if (NULL != resultRelInfo->ri_insertSendBack)
                {
                        Assert(NULL == sendback);
-                       sendback = resultRelInfo->ri_parquetSendBack;
+                       sendback = resultRelInfo->ri_insertSendBack;
                }
 
                if (resultRelInfo->ri_extInsertDesc)
@@ -3390,7 +3391,7 @@ lmark:    ;
                                break;
 
                        case CMD_INSERT:
-                               ExecInsert(slot, dest, estate, PLANGEN_PLANNER, 
false /* isUpdate */);
+                               ExecInsert(slot, dest, estate, PLANGEN_PLANNER, 
false /* isUpdate */, false /* isInputSorted */);
                                result = NULL;
                                break;
 

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/6e6890ae/src/backend/executor/execUtils.c
----------------------------------------------------------------------
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index eb1124d..780fa72 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -278,7 +278,7 @@ InternalCreateExecutorState(MemoryContext qcontext, bool 
is_subquery)
        estate->es_result_relations = NULL;
        estate->es_num_result_relations = 0;
        estate->es_result_relation_info = NULL;
-       estate->es_last_parq_part = InvalidOid;
+       estate->es_last_inserted_part = InvalidOid;
 
        estate->es_junkFilter = NULL;
 

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/6e6890ae/src/backend/executor/nodeDML.c
----------------------------------------------------------------------
diff --git a/src/backend/executor/nodeDML.c b/src/backend/executor/nodeDML.c
index db103ce..5ba48df 100644
--- a/src/backend/executor/nodeDML.c
+++ b/src/backend/executor/nodeDML.c
@@ -120,7 +120,7 @@ ExecDML(DMLState *node)
                 */
                ExecInsert(node->cleanedUpSlot, NULL /* destReceiver */,
                                node->ps.state, PLANGEN_OPTIMIZER /* Plan 
origin */, 
-                               isUpdate);
+                               isUpdate, plannode->inputSorted);
        }
        else /* DML_DELETE */
        {

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/6e6890ae/src/backend/utils/misc/guc.c
----------------------------------------------------------------------
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 4e54ae8..b9a5204 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -6150,7 +6150,7 @@ static struct config_int ConfigureNamesInt[] =
                {"optimizer_parts_to_force_sort_on_insert", PGC_USERSET, 
DEVELOPER_OPTIONS,
                        gettext_noop("Minimum number of partitions required to 
force sorting tuples during insertion in an append only row-oriented 
partitioned table"),
                        NULL,
-                       GUC_NOT_IN_SAMPLE
+                       GUC_NOT_IN_SAMPLE | GUC_GPDB_ADDOPT
                },
                &optimizer_parts_to_force_sort_on_insert,
                INT_MAX, 0, INT_MAX, NULL, NULL

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/6e6890ae/src/include/executor/execDML.h
----------------------------------------------------------------------
diff --git a/src/include/executor/execDML.h b/src/include/executor/execDML.h
index f1f45c8..886b585 100644
--- a/src/include/executor/execDML.h
+++ b/src/include/executor/execDML.h
@@ -54,7 +54,8 @@ ExecInsert(TupleTableSlot *slot,
                   DestReceiver *dest,
                   EState *estate,
                   PlanGenerator planGen,
-                  bool isUpdate);
+                  bool isUpdate,
+                  bool isInputSorted);
 
 extern void
 ExecDelete(ItemPointer tupleid,

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/6e6890ae/src/include/nodes/execnodes.h
----------------------------------------------------------------------
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 98c2ee6..7a2e733 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -278,7 +278,7 @@ typedef struct JunkFilter
  *  aoInsertDesc        context for appendonly relation buffered INSERT
  *  extInsertDesc       context for external table INSERT
  *  parquetInsertDesc   context for parquet table INSERT
- *  parquetSendBack     information to be sent back to dispatch after INSERT 
in a parquet table
+ *  insertSendBack      information to be sent back to dispatch after INSERT 
in a parquet or AO table
  *  aosegno             the AO segfile we inserted into.
  *  aoprocessed         tuples processed for AO
  *  partInsertMap       map input attrno to target attrno
@@ -307,7 +307,8 @@ typedef struct ResultRelInfo
 
        struct ExternalInsertDescData   *ri_extInsertDesc;
        struct ParquetInsertDescData    *ri_parquetInsertDesc;
-       struct QueryContextDispatchingSendBackData *ri_parquetSendBack;
+
+       struct QueryContextDispatchingSendBackData *ri_insertSendBack;
 
        List *ri_aosegnos;
 
@@ -501,7 +502,7 @@ typedef struct EState
        ResultRelInfo *es_result_relation_info;                /* currently 
active array elt */
        JunkFilter *es_junkFilter;        /* currently active junk filter */
 
-       Oid es_last_parq_part; /* The Oid of the last parquet partition we 
opened for insertion */
+       Oid es_last_inserted_part; /* The Oid of the last partition we opened 
for insertion */
 
        /* partitioning info for target relation */
        PartitionNode *es_result_partitions;

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/6e6890ae/src/test/regress/expected/goh_partition.out
----------------------------------------------------------------------
diff --git a/src/test/regress/expected/goh_partition.out 
b/src/test/regress/expected/goh_partition.out
index d636126..b26a76d 100755
--- a/src/test/regress/expected/goh_partition.out
+++ b/src/test/regress/expected/goh_partition.out
@@ -2197,3 +2197,129 @@ NOTICE:  CREATE TABLE will create partition 
"rank3_1_prt_girls_2_prt_jan04_3_prt
 NOTICE:  CREATE TABLE will create partition 
"rank3_1_prt_girls_2_prt_jan05_3_prt_mass" for table 
"rank3_1_prt_girls_2_prt_jan05"
 NOTICE:  CREATE TABLE will create partition 
"rank3_1_prt_girls_2_prt_jan05_3_prt_cali" for table 
"rank3_1_prt_girls_2_prt_jan05"
 NOTICE:  CREATE TABLE will create partition 
"rank3_1_prt_girls_2_prt_jan05_3_prt_ohio" for table 
"rank3_1_prt_girls_2_prt_jan05"
+-- Tests for sort operator before insert with AO and PARQUET tables (HAWQ-404)
+-- A GUC's value is set to less than the number of partitions in the example 
table, so that sort is activated.
+DROP TABLE IF EXISTS ch_sort_src, ch_sort_aodest, ch_sort_pqdest, 
ch_sort_aopqdest, ch_sort__pq_table;
+SET optimizer_parts_to_force_sort_on_insert = 5;
+CREATE TABLE ch_sort_src (id int, year int, month int, day int, region text)
+DISTRIBUTED BY (month); 
+INSERT INTO ch_sort_src select i, 2000 + i, i % 12, (2*i) % 30, i::text from 
generate_series(0, 99) i; 
+-- AO partitioned table
+CREATE TABLE ch_sort_aodest (id int, year int, month int, day int, region text)
+WITH (APPENDONLY=TRUE)
+DISTRIBUTED BY (id)
+PARTITION BY RANGE (year)
+( 
+    START (2002) END (2010) EVERY (1),
+    DEFAULT PARTITION outlying_years
+);
+NOTICE:  CREATE TABLE will create partition 
"ch_sort_aodest_1_prt_outlying_years" for table "ch_sort_aodest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aodest_1_prt_2" for table 
"ch_sort_aodest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aodest_1_prt_3" for table 
"ch_sort_aodest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aodest_1_prt_4" for table 
"ch_sort_aodest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aodest_1_prt_5" for table 
"ch_sort_aodest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aodest_1_prt_6" for table 
"ch_sort_aodest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aodest_1_prt_7" for table 
"ch_sort_aodest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aodest_1_prt_8" for table 
"ch_sort_aodest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aodest_1_prt_9" for table 
"ch_sort_aodest"
+-- PARQUET partitioned table
+CREATE TABLE ch_sort_pqdest (id int, year int, month int, day int, region text)
+WITH (APPENDONLY=TRUE, ORIENTATION = PARQUET)
+DISTRIBUTED BY (id)
+PARTITION BY RANGE (year)
+( 
+    START (2002) END (2010) EVERY (1),
+    DEFAULT PARTITION outlying_years
+);
+NOTICE:  CREATE TABLE will create partition 
"ch_sort_pqdest_1_prt_outlying_years" for table "ch_sort_pqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_pqdest_1_prt_2" for table 
"ch_sort_pqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_pqdest_1_prt_3" for table 
"ch_sort_pqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_pqdest_1_prt_4" for table 
"ch_sort_pqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_pqdest_1_prt_5" for table 
"ch_sort_pqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_pqdest_1_prt_6" for table 
"ch_sort_pqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_pqdest_1_prt_7" for table 
"ch_sort_pqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_pqdest_1_prt_8" for table 
"ch_sort_pqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_pqdest_1_prt_9" for table 
"ch_sort_pqdest"
+-- AO/PARQUET mixed table
+CREATE TABLE ch_sort_aopqdest (id int, year int, month int, day int, region 
text)
+WITH (APPENDONLY=TRUE)
+DISTRIBUTED BY (id)
+PARTITION BY RANGE (year)
+( 
+    START (2002) END (2010) EVERY (1),
+    DEFAULT PARTITION outlying_years
+);
+NOTICE:  CREATE TABLE will create partition 
"ch_sort_aopqdest_1_prt_outlying_years" for table "ch_sort_aopqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aopqdest_1_prt_2" for 
table "ch_sort_aopqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aopqdest_1_prt_3" for 
table "ch_sort_aopqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aopqdest_1_prt_4" for 
table "ch_sort_aopqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aopqdest_1_prt_5" for 
table "ch_sort_aopqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aopqdest_1_prt_6" for 
table "ch_sort_aopqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aopqdest_1_prt_7" for 
table "ch_sort_aopqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aopqdest_1_prt_8" for 
table "ch_sort_aopqdest"
+NOTICE:  CREATE TABLE will create partition "ch_sort_aopqdest_1_prt_9" for 
table "ch_sort_aopqdest"
+CREATE TABLE ch_sort__pq_table (id int, year int, month int, day int, region 
text)
+WITH (APPENDONLY=TRUE, ORIENTATION = PARQUET)
+DISTRIBUTED BY (id);
+ALTER TABLE ch_sort_aopqdest
+EXCHANGE PARTITION FOR(2006)
+WITH TABLE ch_sort__pq_table;
+-- Test that inserts work
+INSERT INTO ch_sort_aodest SELECT * FROM ch_sort_src;
+SELECT COUNT(*) FROM ch_sort_aodest;
+ count 
+-------
+   100
+(1 row)
+
+SELECT COUNT(*) FROM ch_sort_aodest_1_prt_6;
+ count 
+-------
+     1
+(1 row)
+
+SELECT COUNT(*) FROM ch_sort_aodest_1_prt_outlying_years;
+ count 
+-------
+    92
+(1 row)
+
+INSERT INTO ch_sort_pqdest SELECT * FROM ch_sort_src;
+SELECT COUNT(*) FROM ch_sort_pqdest;
+ count 
+-------
+   100
+(1 row)
+
+SELECT COUNT(*) FROM ch_sort_pqdest_1_prt_6;
+ count 
+-------
+     1
+(1 row)
+
+SELECT COUNT(*) FROM ch_sort_pqdest_1_prt_outlying_years;
+ count 
+-------
+    92
+(1 row)
+
+INSERT INTO ch_sort_aopqdest SELECT * FROM ch_sort_src;
+SELECT COUNT(*) FROM ch_sort_aopqdest;
+ count 
+-------
+   100
+(1 row)
+
+SELECT COUNT(*) FROM ch_sort_aopqdest_1_prt_6;
+ count 
+-------
+     1
+(1 row)
+
+SELECT COUNT(*) FROM ch_sort_aopqdest_1_prt_outlying_years;
+ count 
+-------
+    92
+(1 row)
+
+RESET optimizer_parts_to_force_sort_on_insert;

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/6e6890ae/src/test/regress/sql/goh_partition.sql
----------------------------------------------------------------------
diff --git a/src/test/regress/sql/goh_partition.sql 
b/src/test/regress/sql/goh_partition.sql
index 8cea409..4c04bd8 100644
--- a/src/test/regress/sql/goh_partition.sql
+++ b/src/test/regress/sql/goh_partition.sql
@@ -1227,3 +1227,71 @@ subpartition ohio values ('OH')
 )
 )
 );
+
+-- Tests for sort operator before insert with AO and PARQUET tables (HAWQ-404)
+-- A GUC's value is set to less than the number of partitions in the example 
table, so that sort is activated.
+
+DROP TABLE IF EXISTS ch_sort_src, ch_sort_aodest, ch_sort_pqdest, 
ch_sort_aopqdest, ch_sort__pq_table;
+
+SET optimizer_parts_to_force_sort_on_insert = 5;
+
+CREATE TABLE ch_sort_src (id int, year int, month int, day int, region text)
+DISTRIBUTED BY (month); 
+INSERT INTO ch_sort_src select i, 2000 + i, i % 12, (2*i) % 30, i::text from 
generate_series(0, 99) i; 
+
+-- AO partitioned table
+CREATE TABLE ch_sort_aodest (id int, year int, month int, day int, region text)
+WITH (APPENDONLY=TRUE)
+DISTRIBUTED BY (id)
+PARTITION BY RANGE (year)
+( 
+    START (2002) END (2010) EVERY (1),
+    DEFAULT PARTITION outlying_years
+);
+
+-- PARQUET partitioned table
+CREATE TABLE ch_sort_pqdest (id int, year int, month int, day int, region text)
+WITH (APPENDONLY=TRUE, ORIENTATION = PARQUET)
+DISTRIBUTED BY (id)
+PARTITION BY RANGE (year)
+( 
+    START (2002) END (2010) EVERY (1),
+    DEFAULT PARTITION outlying_years
+);
+
+-- AO/PARQUET mixed table
+CREATE TABLE ch_sort_aopqdest (id int, year int, month int, day int, region 
text)
+WITH (APPENDONLY=TRUE)
+DISTRIBUTED BY (id)
+PARTITION BY RANGE (year)
+( 
+    START (2002) END (2010) EVERY (1),
+    DEFAULT PARTITION outlying_years
+);
+
+CREATE TABLE ch_sort__pq_table (id int, year int, month int, day int, region 
text)
+WITH (APPENDONLY=TRUE, ORIENTATION = PARQUET)
+DISTRIBUTED BY (id);
+
+ALTER TABLE ch_sort_aopqdest
+EXCHANGE PARTITION FOR(2006)
+WITH TABLE ch_sort__pq_table;
+
+
+-- Test that inserts work
+INSERT INTO ch_sort_aodest SELECT * FROM ch_sort_src;
+SELECT COUNT(*) FROM ch_sort_aodest;
+SELECT COUNT(*) FROM ch_sort_aodest_1_prt_6;
+SELECT COUNT(*) FROM ch_sort_aodest_1_prt_outlying_years;
+
+INSERT INTO ch_sort_pqdest SELECT * FROM ch_sort_src;
+SELECT COUNT(*) FROM ch_sort_pqdest;
+SELECT COUNT(*) FROM ch_sort_pqdest_1_prt_6;
+SELECT COUNT(*) FROM ch_sort_pqdest_1_prt_outlying_years;
+
+INSERT INTO ch_sort_aopqdest SELECT * FROM ch_sort_src;
+SELECT COUNT(*) FROM ch_sort_aopqdest;
+SELECT COUNT(*) FROM ch_sort_aopqdest_1_prt_6;
+SELECT COUNT(*) FROM ch_sort_aopqdest_1_prt_outlying_years;
+
+RESET optimizer_parts_to_force_sort_on_insert;

Reply via email to