[ASTERIXDB-2687][RT] Issue a warning when incomparable types are compared

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
Issue a warning when NULL was returned as the result of a comparison
of 2 incomparable types.

- added error/warning code 49
- refactored dot format plans generator
- removed some AQL tests that are already covered in SQL++ tests

Change-Id: Iad3127e4db775315817a7819feea6aa12e4de2ea
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/4464
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <tillw@apache.org>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/ComparisonQueries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/ComparisonQueries.xml
index 56df4ad..09845d8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/ComparisonQueries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/ComparisonQueries.xml
@@ -175,41 +175,6 @@
     </compilation-unit>
   </test-case>
   <test-case FilePath="comparison">
-    <compilation-unit name="issue363_inequality_duration">
-      <output-dir compare="Text">issue363_inequality_duration</output-dir>
-    </compilation-unit>
-  </test-case>
-  <test-case FilePath="comparison">
-    <compilation-unit name="issue363_inequality_interval">
-      <output-dir compare="Text">issue363_inequality_interval</output-dir>
-    </compilation-unit>
-  </test-case>
-  <test-case FilePath="comparison">
-    <compilation-unit name="issue363_inequality_point">
-      <output-dir compare="Text">issue363_inequality_point</output-dir>
-    </compilation-unit>
-  </test-case>
-  <test-case FilePath="comparison">
-    <compilation-unit name="issue363_inequality_line">
-      <output-dir compare="Text">issue363_inequality_line</output-dir>
-    </compilation-unit>
-  </test-case>
-  <test-case FilePath="comparison">
-    <compilation-unit name="issue363_inequality_polygon">
-      <output-dir compare="Text">issue363_inequality_polygon</output-dir>
-    </compilation-unit>
-  </test-case>
-  <test-case FilePath="comparison">
-    <compilation-unit name="issue363_inequality_rectangle">
-      <output-dir compare="Text">issue363_inequality_rectangle</output-dir>
-    </compilation-unit>
-  </test-case>
-  <test-case FilePath="comparison">
-    <compilation-unit name="issue363_inequality_circle">
-      <output-dir compare="Text">issue363_inequality_circle</output-dir>
-    </compilation-unit>
-  </test-case>
-  <test-case FilePath="comparison">
     <compilation-unit name="binary">
       <output-dir compare="Text">binary</output-dir>
     </compilation-unit>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_circle/issue363_inequality_circle.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_circle/issue363_inequality_circle.1.ddl.aql
deleted file mode 100644
index 2ffaa10..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_circle/issue363_inequality_circle.1.ddl.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of circle
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_circle/issue363_inequality_circle.2.update.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_circle/issue363_inequality_circle.2.update.aql
deleted file mode 100644
index 2ffaa10..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_circle/issue363_inequality_circle.2.update.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of circle
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_circle/issue363_inequality_circle.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_circle/issue363_inequality_circle.3.query.aql
deleted file mode 100644
index 9dbc490..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_circle/issue363_inequality_circle.3.query.aql
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of circle
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
- 
-let $v1 := circle("0.1234,-1.00e-10 +10.5E-2")
-let $dv1 := circle("0.5678,-1.00e-10 +10.5E-2")
-
-return { "circle0":  $v1 > $dv1, "circle1": $dv1 < $v1, "circle2":  $v1 >= $dv1, "circle3": $dv1 <= $v1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.2.update.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.2.update.aql
deleted file mode 100644
index b0a772c..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.2.update.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of duration
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.3.query.aql
deleted file mode 100644
index 1c47674..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.3.query.aql
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of duration
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
- 
-let $v1 := duration("P300Y6M3DT9H5M2.348S")
-let $dv1 := duration("P3Y6M3DT9H5M2.348S")
-
-return { "duration0":  $v1 > $dv1, "duration1": $dv1 < $v1, "duration2":  $v1 >= $dv1, "duration3": $dv1 <= $v1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_interval/issue363_inequality_interval.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_interval/issue363_inequality_interval.1.ddl.aql
deleted file mode 100644
index 4cc0a14..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_interval/issue363_inequality_interval.1.ddl.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of interval
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_interval/issue363_inequality_interval.2.update.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_interval/issue363_inequality_interval.2.update.aql
deleted file mode 100644
index 4cc0a14..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_interval/issue363_inequality_interval.2.update.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of interval
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_interval/issue363_inequality_interval.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_interval/issue363_inequality_interval.3.query.aql
deleted file mode 100644
index 9d1a868..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_interval/issue363_inequality_interval.3.query.aql
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of interval
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
-
-let $v1 := interval(datetime("-1987-11-19T02:43:57.938+08:00"), datetime("19991112T124935948-0700"))
-let $dv1 := interval(datetime("-1983-11-19T02:43:57.938+08:00"), datetime("19991112T124935948-0700"))
-
-return { "interval0":  $v1 > $dv1, "interval1": $dv1 < $v1, "interval2":  $v1 >= $dv1, "interval3": $dv1 <= $v1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_line/issue363_inequality_line.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_line/issue363_inequality_line.1.ddl.aql
deleted file mode 100644
index 104f28d..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_line/issue363_inequality_line.1.ddl.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of line
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_line/issue363_inequality_line.2.update.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_line/issue363_inequality_line.2.update.aql
deleted file mode 100644
index 104f28d..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_line/issue363_inequality_line.2.update.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of line
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_line/issue363_inequality_line.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_line/issue363_inequality_line.3.query.aql
deleted file mode 100644
index 2dbca92..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_line/issue363_inequality_line.3.query.aql
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of line
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
- 
-let $v1 := line("10.1234,11.1e-1 +10.2E-2,-11.22")
-let $dv1 := line("10.1234,11.1e-1 +10.2E-2,-11.22")
-
-return { "line0":  $v1 > $dv1, "line1": $dv1 < $v1, "line2":  $v1 >= $dv1, "line3": $dv1 <= $v1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_point/issue363_inequality_point.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_point/issue363_inequality_point.1.ddl.aql
deleted file mode 100644
index 2d94d3c..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_point/issue363_inequality_point.1.ddl.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of point
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_point/issue363_inequality_point.2.update.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_point/issue363_inequality_point.2.update.aql
deleted file mode 100644
index 2d94d3c..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_point/issue363_inequality_point.2.update.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of point
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_point/issue363_inequality_point.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_point/issue363_inequality_point.3.query.aql
deleted file mode 100644
index 04105cc..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_point/issue363_inequality_point.3.query.aql
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of point
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
- 
-let $v1 := point("47.44,80.65")
-let $dv1 := point("47.4444,80.65")
-
-return { "point0":  $v1 > $dv1, "point1": $dv1 < $v1, "point2":  $v1 >= $dv1, "point3": $dv1 <= $v1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_polygon/issue363_inequality_polygon.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_polygon/issue363_inequality_polygon.1.ddl.aql
deleted file mode 100644
index b9de498..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_polygon/issue363_inequality_polygon.1.ddl.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of polygon
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_polygon/issue363_inequality_polygon.2.update.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_polygon/issue363_inequality_polygon.2.update.aql
deleted file mode 100644
index b9de498..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_polygon/issue363_inequality_polygon.2.update.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of polygon
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_polygon/issue363_inequality_polygon.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_polygon/issue363_inequality_polygon.3.query.aql
deleted file mode 100644
index 1fb676a..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_polygon/issue363_inequality_polygon.3.query.aql
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of polygon
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
- 
-let $v1 := polygon("-1.0,+10.5e2 -02.15E+50,2.5 -1.0,+3.3e3 -2.50E+05,20.15 +3.5e+2,03.6 -4.60E-3,+4.75 -2,+1.0e2 -2.00E+5,20.10 30.5,03.25 -4.33E-3,+4.75")
-let $dv1 := polygon("-1.0,+10.5e2 -02.19E+50,2.5 -1.0,+3.3e3 -2.50E+05,20.15 +3.5e+2,03.6 -4.60E-3,+4.75 -2,+1.0e2 -2.00E+5,20.10 30.5,03.25 -4.33E-3,+4.75")
-
-return { "polygon0":  $v1 > $dv1, "polygon1": $dv1 < $v1, "polygon2":  $v1 >= $dv1, "polygon3": $dv1 <= $v1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_rectangle/issue363_inequality_rectangle.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_rectangle/issue363_inequality_rectangle.1.ddl.aql
deleted file mode 100644
index 98b797d..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_rectangle/issue363_inequality_rectangle.1.ddl.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of rectangle
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_rectangle/issue363_inequality_rectangle.2.update.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_rectangle/issue363_inequality_rectangle.2.update.aql
deleted file mode 100644
index 98b797d..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_rectangle/issue363_inequality_rectangle.2.update.aql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of rectangle
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_rectangle/issue363_inequality_rectangle.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_rectangle/issue363_inequality_rectangle.3.query.aql
deleted file mode 100644
index 378aaae..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_rectangle/issue363_inequality_rectangle.3.query.aql
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Description  : a test case for inequality comparisons of rectangle
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
- 
-let $v1 := rectangle("0.1234,-1.00e-10 5.5487,0.48765")
-let $dv1 := rectangle("0.5678,-1.00e-10 5.5487,0.48765")
-
-return { "rectangle0":  $v1 > $dv1, "rectangle1": $dv1 < $v1, "rectangle2":  $v1 >= $dv1, "rectangle3": $dv1 <= $v1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.001.ddl.sqlpp
similarity index 80%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.001.ddl.sqlpp
index b0a772c..6c25dfd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.001.ddl.sqlpp
@@ -16,9 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/*
- * Description  : a test case for inequality comparisons of duration
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+create type openType as {id:int};
+
+create dataset ds1(openType) primary key id;
+create dataset ds2(openType) primary key id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.002.update.sqlpp
similarity index 83%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.002.update.sqlpp
index b0a772c..ee7136f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.002.update.sqlpp
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/*
- * Description  : a test case for inequality comparisons of duration
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
+
+use test;
+
+insert into ds1 {"id": 1, "f": 5};
+insert into ds1 {"id": 2, "f": "str"};
+insert into ds2 {"id": 1, "f": "str"};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.003.query.sqlpp
similarity index 83%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.003.query.sqlpp
index b0a772c..66e6595 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.003.query.sqlpp
@@ -16,9 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/*
- * Description  : a test case for inequality comparisons of duration
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
+
+-- param max-warnings:string=10
+
+use test;
+
+from ds1 join ds2 on ds1.f /*+ hash-bcast */ = ds2.f
+where ds1.f > 1
+select ds1.f;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.004.query.sqlpp
similarity index 83%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.004.query.sqlpp
index b0a772c..a61ae14 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.004.query.sqlpp
@@ -16,9 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/*
- * Description  : a test case for inequality comparisons of duration
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
+
+-- param max-warnings:string=10
+
+from [
+[1,2] < 4,
+point('0.0,0.0') < point('0.0,1.0')
+] as data
+select data;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.005.ddl.sqlpp
similarity index 83%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.005.ddl.sqlpp
index b0a772c..548e632 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries/comparison/issue363_inequality_duration/issue363_inequality_duration.1.ddl.aql
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/comparison/incomparable_types/incomparable_types.005.ddl.sqlpp
@@ -16,9 +16,5 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/*
- * Description  : a test case for inequality comparisons of duration
- * Expected Res : Failure
- * Date         : 9 May 2013
- * Issue        : 363
- */
+
+drop dataverse test if exists;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/incomparable_types/incomparable_types.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/incomparable_types/incomparable_types.1.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/incomparable_types/incomparable_types.1.adm
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/incomparable_types/incomparable_types.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/incomparable_types/incomparable_types.2.adm
new file mode 100644
index 0000000..b036da7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/comparison/incomparable_types/incomparable_types.2.adm
@@ -0,0 +1,2 @@
+{ "data": null }
+{ "data": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index bf16d65..2b3cb77 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -3367,6 +3367,14 @@
         <output-dir compare="Text">circle-point</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="comparison" check-warnings="true">
+      <compilation-unit name="incomparable_types">
+        <output-dir compare="Text">incomparable_types</output-dir>
+          <expected-warn>Incomparable input types: string and bigint (in line 25, at column 13)</expected-warn>
+          <expected-warn>Incomparable input types: array and bigint (in line 23, at column 7)</expected-warn>
+          <expected-warn>Incomparable input types: point and point (in line 24, at column 18)</expected-warn>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="constructor">
     <test-case FilePath="constructor">
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index da1c4e7..95cd4a8 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -81,6 +81,7 @@
     public static final int INVALID_LIKE_PATTERN = 46;
     public static final int INVALID_REQ_PARAM_VAL = 47;
     public static final int INVALID_REQ_JSON_VAL = 48;
+    public static final int INCOMPARABLE_TYPES = 49;
 
     public static final int UNSUPPORTED_JRE = 100;
 
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index 457206d..12d7284 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -40,7 +40,7 @@
 13,1006 = Duplicate field name \"%1$s\"
 1009 = A returning expression cannot contain dataset access
 37,1091 = Type mismatch: expected value of type %1$s, but got the value of type %2$s
-
+49 = Incomparable input types: %1$s and %2$s
 
 # Data errors
 6 = Invalid format for %1$s in %2$s
@@ -83,6 +83,7 @@
 46 = Invalid pattern \"%1$s\" for LIKE
 47 = Invalid value for parameter \"%1$s\": %2$s
 48 = Unable to process JSON content in request
+#49 is used
 
 100 = Unsupported JRE: %1$s
 
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/exceptions/ExceptionUtil.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/exceptions/ExceptionUtil.java
index b5d599b..ec844ce 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/exceptions/ExceptionUtil.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/exceptions/ExceptionUtil.java
@@ -124,6 +124,14 @@
         }
     }
 
+    public static void warnIncomparableTypes(IEvaluatorContext ctx, SourceLocation srcLoc, ATypeTag type1,
+            ATypeTag type2) {
+        IWarningCollector warningCollector = ctx.getWarningCollector();
+        if (warningCollector.shouldWarn()) {
+            warningCollector.warn(WarningUtil.forAsterix(srcLoc, ErrorCode.INCOMPARABLE_TYPES, type1, type2));
+        }
+    }
+
     /** For functions that accept an integer value (no fractions) of any numeric type including double & float */
     public static void warnNonInteger(IEvaluatorContext ctx, SourceLocation srcLoc, FunctionIdentifier fid, int argIdx,
             double argValue) {
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractComparisonEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractComparisonEvaluator.java
index 244ffc3..668548d 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractComparisonEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractComparisonEvaluator.java
@@ -70,19 +70,21 @@
     protected final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
     protected final DataOutput out = resultStorage.getDataOutput();
     protected final TaggedValuePointable argLeft = TaggedValuePointable.FACTORY.createPointable();
-    private final TaggedValuePointable argRight = TaggedValuePointable.FACTORY.createPointable();
+    protected final TaggedValuePointable argRight = TaggedValuePointable.FACTORY.createPointable();
+    protected final SourceLocation sourceLoc;
+    protected final IEvaluatorContext ctx;
     private final TaggedValueReference leftVal = new TaggedValueReference();
     private final TaggedValueReference rightVal = new TaggedValueReference();
     private final IScalarEvaluator evalLeft;
     private final IScalarEvaluator evalRight;
-    protected final SourceLocation sourceLoc;
     private final ILogicalBinaryComparator logicalComparator;
-    private IAObject leftConstant;
-    private IAObject rightConstant;
+    private final IAObject leftConstant;
+    private final IAObject rightConstant;
 
-    public AbstractComparisonEvaluator(IScalarEvaluatorFactory evalLeftFactory, IAType leftType,
+    AbstractComparisonEvaluator(IScalarEvaluatorFactory evalLeftFactory, IAType leftType,
             IScalarEvaluatorFactory evalRightFactory, IAType rightType, IEvaluatorContext ctx, SourceLocation sourceLoc,
             boolean isEquality) throws HyracksDataException {
+        this.ctx = ctx;
         this.evalLeft = evalLeftFactory.createScalarEvaluator(ctx);
         this.evalRight = evalRightFactory.createScalarEvaluator(ctx);
         this.sourceLoc = sourceLoc;
@@ -91,11 +93,8 @@
         rightConstant = getValueOfConstantEval(evalRightFactory);
     }
 
-    private IAObject getValueOfConstantEval(IScalarEvaluatorFactory factory) {
-        if (factory instanceof ConstantEvalFactory) {
-            return getConstantValue(((ConstantEvalFactory) factory).getValue());
-        }
-        return null;
+    private static IAObject getValueOfConstantEval(IScalarEvaluatorFactory factory) {
+        return factory instanceof ConstantEvalFactory ? getConstant(((ConstantEvalFactory) factory).getValue()) : null;
     }
 
     @Override
@@ -118,20 +117,11 @@
 
     final Result compare() throws HyracksDataException {
         if (leftConstant != null) {
-            if (rightConstant != null) {
-                // both are constants
-                return logicalComparator.compare(leftConstant, rightConstant);
-            } else {
-                // left is constant, right isn't
-                return logicalComparator.compare(leftConstant, rightVal);
-            }
+            return rightConstant != null ? logicalComparator.compare(leftConstant, rightConstant)
+                    : logicalComparator.compare(leftConstant, rightVal);
         } else {
-            if (rightConstant != null) {
-                // right is constant, left isn't
-                return logicalComparator.compare(leftVal, rightConstant);
-            } else {
-                return logicalComparator.compare(leftVal, rightVal);
-            }
+            return rightConstant != null ? logicalComparator.compare(leftVal, rightConstant)
+                    : logicalComparator.compare(leftVal, rightVal);
         }
     }
 
@@ -147,7 +137,7 @@
         result.set(resultStorage);
     }
 
-    private IAObject getConstantValue(byte[] bytes) {
+    private static IAObject getConstant(byte[] bytes) {
         int start = 0;
         ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes[start]);
         if (typeTag == null) {
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractIfEqualsEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractIfEqualsEvaluator.java
index 37b5bb8..1d6a7dc 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractIfEqualsEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractIfEqualsEvaluator.java
@@ -36,6 +36,7 @@
 
     @Override
     protected void evaluateImpl(IPointable result) throws HyracksDataException {
+        // TODO(ali): revisit this for the cases of MISSING/NULL/INCOMPARABLE
         switch (compare()) {
             case MISSING:
                 writeMissing(result);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractValueComparisonEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractValueComparisonEvaluator.java
index 24b655d8..54af8f7 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractValueComparisonEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/comparisons/AbstractValueComparisonEvaluator.java
@@ -19,9 +19,12 @@
 
 package org.apache.asterix.runtime.evaluators.comparisons;
 
+import static org.apache.asterix.om.types.ATypeTag.VALUE_TYPE_MAPPING;
+
 import org.apache.asterix.dataflow.data.common.ILogicalBinaryComparator.Result;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 import org.apache.asterix.om.base.ABoolean;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
 import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
@@ -50,12 +53,16 @@
                 writeMissing(result);
                 break;
             case NULL:
+                writeNull(result);
+                break;
             case INCOMPARABLE:
+                ExceptionUtil.warnIncomparableTypes(ctx, sourceLoc, VALUE_TYPE_MAPPING[argLeft.getTag()],
+                        VALUE_TYPE_MAPPING[argRight.getTag()]);
                 writeNull(result);
                 break;
             default:
                 resultStorage.reset();
-                ABoolean b = getComparisonResult(comparisonResult) ? ABoolean.TRUE : ABoolean.FALSE;
+                ABoolean b = ABoolean.valueOf(getComparisonResult(comparisonResult));
                 serde.serialize(b, out);
                 result.set(resultStorage);
         }
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/utils/DotFormatGenerator.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/utils/DotFormatGenerator.java
index d6895e3..5402751 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/utils/DotFormatGenerator.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/utils/DotFormatGenerator.java
@@ -19,13 +19,9 @@
 package org.apache.hyracks.algebricks.core.utils;
 
 import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
@@ -34,136 +30,13 @@
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractReplicateOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.ExchangeOperator;
-import org.apache.hyracks.api.constraints.Constraint;
-import org.apache.hyracks.api.constraints.expressions.ConstraintExpression;
-import org.apache.hyracks.api.constraints.expressions.LValueConstraintExpression;
-import org.apache.hyracks.api.constraints.expressions.PartitionCountExpression;
-import org.apache.hyracks.api.constraints.expressions.PartitionLocationExpression;
-import org.apache.hyracks.api.dataflow.ActivityId;
-import org.apache.hyracks.api.dataflow.ConnectorDescriptorId;
-import org.apache.hyracks.api.dataflow.IActivity;
-import org.apache.hyracks.api.dataflow.IConnectorDescriptor;
-import org.apache.hyracks.api.dataflow.IOperatorDescriptor;
-import org.apache.hyracks.api.job.JobActivityGraph;
-import org.apache.hyracks.api.job.JobSpecification;
+import org.apache.hyracks.api.util.DotFormatBuilder;
 
 public class DotFormatGenerator {
 
     private final LogicalOperatorDotVisitor dotVisitor = new LogicalOperatorDotVisitor();
 
     /**
-     * Generates DOT format plan for {@link JobActivityGraph} that can be visualized using any DOT format visualizer.
-     *
-     * @param jobActivityGraph The job activity graph
-     * @return DOT format plan
-     */
-    public static String generate(final JobActivityGraph jobActivityGraph) {
-        final DotFormatBuilder graphBuilder = new DotFormatBuilder(DotFormatBuilder.StringValue.of("JobActivityGraph"));
-        List<IConnectorDescriptor> connectors;
-        IActivity activity;
-        ActivityId fromActivityId;
-        ActivityId toActivityId;
-        String fromFullClassName;
-        String toFullClassName;
-        String fromClassName;
-        String toClassName;
-        DotFormatBuilder.Node fromNode;
-        DotFormatBuilder.Node toNode;
-        final Set<Pair<ActivityId, ActivityId>> activitiesPairedSet = new HashSet<>();
-        final Map<ActivityId, IActivity> activityMap = jobActivityGraph.getActivityMap();
-        final Map<ActivityId, List<IConnectorDescriptor>> activityInputMap = jobActivityGraph.getActivityInputMap();
-        final Map<ActivityId, List<IConnectorDescriptor>> activityOutputMap = jobActivityGraph.getActivityOutputMap();
-
-        // go through each activity. First, map its input -> activity, then activity -> its output
-        for (Map.Entry<ActivityId, IActivity> entry : activityMap.entrySet()) {
-            toFullClassName = entry.getValue().getClass().getName();
-            toClassName = toFullClassName.substring(toFullClassName.lastIndexOf('.') + 1);
-            toActivityId = entry.getValue().getActivityId();
-            toNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(toActivityId.toString()),
-                    DotFormatBuilder.StringValue.of(toActivityId.toString() + "-" + toClassName));
-            // process input -> to activity
-            connectors = activityInputMap.get(entry.getKey());
-            if (connectors != null) {
-                for (IConnectorDescriptor connector : connectors) {
-                    fromActivityId = jobActivityGraph.getProducerActivity(connector.getConnectorId());
-                    activity = activityMap.get(fromActivityId);
-                    fromFullClassName = activity.getClass().getName();
-                    fromClassName = fromFullClassName.substring(fromFullClassName.lastIndexOf('.') + 1);
-                    fromNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(fromActivityId.toString()),
-                            DotFormatBuilder.StringValue.of(fromActivityId.toString() + "-" + fromClassName));
-                    Pair<ActivityId, ActivityId> newPair = new ImmutablePair<>(fromActivityId, toActivityId);
-                    if (!activitiesPairedSet.contains(newPair)) {
-                        activitiesPairedSet.add(newPair);
-                        graphBuilder.createEdge(fromNode, toNode);
-                    }
-                }
-            }
-
-            // process from activity -> output
-            fromActivityId = toActivityId;
-            fromNode = toNode;
-            connectors = activityOutputMap.get(entry.getKey());
-            if (connectors != null) {
-                for (IConnectorDescriptor connector : connectors) {
-                    toActivityId = jobActivityGraph.getConsumerActivity(connector.getConnectorId());
-                    activity = activityMap.get(toActivityId);
-                    toFullClassName = activity.getClass().getName();
-                    toClassName = toFullClassName.substring(toFullClassName.lastIndexOf('.') + 1);
-                    toNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(toActivityId.toString()),
-                            DotFormatBuilder.StringValue.of(toActivityId.toString() + "-" + toClassName));
-                    Pair<ActivityId, ActivityId> newPair = new ImmutablePair<>(fromActivityId, toActivityId);
-                    if (!activitiesPairedSet.contains(newPair)) {
-                        activitiesPairedSet.add(newPair);
-                        graphBuilder.createEdge(fromNode, toNode);
-                    }
-                }
-            }
-        }
-
-        final Map<ActivityId, Set<ActivityId>> blocked2BlockerMap = jobActivityGraph.getBlocked2BlockerMap();
-        IActivity blockedActivity;
-        for (Map.Entry<ActivityId, Set<ActivityId>> entry : blocked2BlockerMap.entrySet()) {
-            blockedActivity = activityMap.get(entry.getKey());
-            toFullClassName = blockedActivity.getClass().getName();
-            toClassName = toFullClassName.substring(toFullClassName.lastIndexOf('.') + 1);
-            toActivityId = entry.getKey();
-            toNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(toActivityId.toString()),
-                    DotFormatBuilder.StringValue.of(toActivityId.toString() + "-" + toClassName));
-            for (ActivityId blockingActivityId : entry.getValue()) {
-                fromActivityId = blockingActivityId;
-                activity = activityMap.get(fromActivityId);
-                fromFullClassName = activity.getClass().getName();
-                fromClassName = fromFullClassName.substring(fromFullClassName.lastIndexOf('.') + 1);
-                fromNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(fromActivityId.toString()),
-                        DotFormatBuilder.StringValue.of(fromActivityId.toString() + "-" + fromClassName));
-                Pair<ActivityId, ActivityId> newPair = new ImmutablePair<>(fromActivityId, toActivityId);
-                if (!activitiesPairedSet.contains(newPair)) {
-                    activitiesPairedSet.add(newPair);
-                    graphBuilder.createEdge(fromNode, toNode).setColor(DotFormatBuilder.Color.RED);
-                }
-            }
-        }
-
-        return graphBuilder.getDotDocument();
-    }
-
-    /**
-     * Generates DOT format plan for {@link JobSpecification} that can be visualized using any DOT format visualizer.
-     *
-     * @param jobSpecification The job specification
-     * @return DOT format plan
-     */
-    public static String generate(final JobSpecification jobSpecification) {
-        final DotFormatBuilder graphBuilder = new DotFormatBuilder(DotFormatBuilder.StringValue.of("JobSpecification"));
-        final Map<ConnectorDescriptorId, IConnectorDescriptor> connectorMap = jobSpecification.getConnectorMap();
-        final Set<Constraint> constraints = jobSpecification.getUserConstraints();
-        Map<ConnectorDescriptorId, Pair<Pair<IOperatorDescriptor, Integer>, Pair<IOperatorDescriptor, Integer>>> cOp =
-                jobSpecification.getConnectorOperatorMap();
-        cOp.forEach((connId, srcAndDest) -> addToGraph(graphBuilder, constraints, connectorMap, connId, srcAndDest));
-        return graphBuilder.getDotDocument();
-    }
-
-    /**
      * Generates DOT format plan for {@link ILogicalPlan} that can be visualized using any DOT format visualizer.
      *
      * @param plan  The logical plan
@@ -250,47 +123,4 @@
         String formattedString = operator.accept(dotVisitor, showDetails).trim();
         return DotFormatBuilder.StringValue.of(formattedString);
     }
-
-    private static void addToGraph(DotFormatBuilder graph, Set<Constraint> constraints,
-            Map<ConnectorDescriptorId, IConnectorDescriptor> connMap, ConnectorDescriptorId connId,
-            Pair<Pair<IOperatorDescriptor, Integer>, Pair<IOperatorDescriptor, Integer>> srcAndDest) {
-        IConnectorDescriptor connector = connMap.get(connId);
-        String edgeLabel;
-        edgeLabel = connector.getClass().getName().substring(connector.getClass().getName().lastIndexOf(".") + 1);
-        edgeLabel += "-" + connId;
-        IOperatorDescriptor sourceOp = srcAndDest.getLeft().getLeft();
-        IOperatorDescriptor destOp = srcAndDest.getRight().getLeft();
-        StringBuilder source = new StringBuilder(
-                sourceOp.getClass().getName().substring(sourceOp.getClass().getName().lastIndexOf(".") + 1));
-        StringBuilder destination = new StringBuilder(
-                destOp.getClass().getName().substring(destOp.getClass().getName().lastIndexOf(".") + 1));
-        // constraints
-        for (Constraint constraint : constraints) {
-            LValueConstraintExpression lvalue = constraint.getLValue();
-            if (lvalue.getTag() == ConstraintExpression.ExpressionTag.PARTITION_COUNT) {
-                PartitionCountExpression count = (PartitionCountExpression) lvalue;
-                if (count.getOperatorDescriptorId().equals(sourceOp.getOperatorId())) {
-                    source.append("\n").append(constraint);
-                }
-                if (count.getOperatorDescriptorId().equals(destOp.getOperatorId())) {
-                    destination.append("\n").append(constraint);
-                }
-            } else if (lvalue.getTag() == ConstraintExpression.ExpressionTag.PARTITION_LOCATION) {
-                PartitionLocationExpression location = (PartitionLocationExpression) lvalue;
-                if (location.getOperatorDescriptorId().equals(sourceOp.getOperatorId())) {
-                    source.append("\n").append(constraint);
-                }
-                if (location.getOperatorDescriptorId().equals(destOp.getOperatorId())) {
-                    destination.append("\n").append(constraint);
-                }
-            }
-        }
-        DotFormatBuilder.Node sourceNode =
-                graph.createNode(DotFormatBuilder.StringValue.of(sourceOp.getOperatorId().toString()),
-                        DotFormatBuilder.StringValue.of(sourceOp.toString() + "-" + source));
-        DotFormatBuilder.Node destinationNode =
-                graph.createNode(DotFormatBuilder.StringValue.of(destOp.getOperatorId().toString()),
-                        DotFormatBuilder.StringValue.of(destOp.toString() + "-" + destination));
-        graph.createEdge(sourceNode, destinationNode).setLabel(DotFormatBuilder.StringValue.of(edgeLabel));
-    }
 }
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/utils/DotFormatBuilder.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/DotFormatBuilder.java
similarity index 92%
rename from hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/utils/DotFormatBuilder.java
rename to hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/DotFormatBuilder.java
index e782e4f..9f9b4fa 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/utils/DotFormatBuilder.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/DotFormatBuilder.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.hyracks.algebricks.core.utils;
+package org.apache.hyracks.api.util;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -164,6 +164,11 @@
             return this;
         }
 
+        public Edge setDashed() {
+            attributes.put(Attribute.STYLE, Style.DASHED);
+            return this;
+        }
+
         @Override
         public boolean equals(Object other) {
             if (!(other instanceof Edge)) {
@@ -231,6 +236,7 @@
     public static final class Color extends AttributeValue {
         public static final Color RED = new Color("red");
         public static final Color SKYBLUE = new Color("skyblue");
+        public static final Color BLUE = new Color("blue");
 
         // no instantiation
         private Color(String color) {
@@ -238,9 +244,19 @@
         }
     }
 
-    private class Attribute {
+    public static final class Style extends AttributeValue {
+        public static final Style DASHED = new Style("dashed");
+
+        // no instantiation
+        private Style(String style) {
+            super(style);
+        }
+    }
+
+    private static final class Attribute {
         private static final String COLOR = "color";
         private static final String LABEL = "label";
+        private static final String STYLE = "style";
 
         // no instantiation
         private Attribute() {
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/DotFormatGenerator.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/DotFormatGenerator.java
new file mode 100644
index 0000000..10ae66e
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/DotFormatGenerator.java
@@ -0,0 +1,203 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.hyracks.api.util;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.hyracks.api.constraints.Constraint;
+import org.apache.hyracks.api.constraints.expressions.ConstraintExpression;
+import org.apache.hyracks.api.constraints.expressions.LValueConstraintExpression;
+import org.apache.hyracks.api.constraints.expressions.PartitionCountExpression;
+import org.apache.hyracks.api.constraints.expressions.PartitionLocationExpression;
+import org.apache.hyracks.api.dataflow.ActivityId;
+import org.apache.hyracks.api.dataflow.ConnectorDescriptorId;
+import org.apache.hyracks.api.dataflow.IActivity;
+import org.apache.hyracks.api.dataflow.IConnectorDescriptor;
+import org.apache.hyracks.api.dataflow.IOperatorDescriptor;
+import org.apache.hyracks.api.job.JobActivityGraph;
+import org.apache.hyracks.api.job.JobSpecification;
+
+public final class DotFormatGenerator {
+
+    /**
+     * Generates DOT format plan for {@link JobActivityGraph} that can be visualized using any DOT format visualizer.
+     *
+     * @param jobActivityGraph The job activity graph
+     * @return DOT format plan
+     */
+    public static String generate(final JobActivityGraph jobActivityGraph) {
+        final DotFormatBuilder graphBuilder = new DotFormatBuilder(DotFormatBuilder.StringValue.of("JobActivityGraph"));
+        List<IConnectorDescriptor> connectors;
+        IActivity activity;
+        ActivityId fromActivityId;
+        ActivityId toActivityId;
+        String fromFullClassName;
+        String toFullClassName;
+        String fromClassName;
+        String toClassName;
+        DotFormatBuilder.Node fromNode;
+        DotFormatBuilder.Node toNode;
+        final Set<Pair<ActivityId, ActivityId>> activitiesPairedSet = new HashSet<>();
+        final Map<ActivityId, IActivity> activityMap = jobActivityGraph.getActivityMap();
+        final Map<ActivityId, List<IConnectorDescriptor>> activityInputMap = jobActivityGraph.getActivityInputMap();
+        final Map<ActivityId, List<IConnectorDescriptor>> activityOutputMap = jobActivityGraph.getActivityOutputMap();
+
+        // go through each activity. First, map its input -> activity, then activity -> its output
+        for (Map.Entry<ActivityId, IActivity> entry : activityMap.entrySet()) {
+            toFullClassName = entry.getValue().getClass().getName();
+            toClassName = toFullClassName.substring(toFullClassName.lastIndexOf('.') + 1);
+            toActivityId = entry.getValue().getActivityId();
+            toNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(toActivityId.toString()),
+                    DotFormatBuilder.StringValue.of(toActivityId.toString() + "-" + toClassName));
+            // process input -> to activity
+            connectors = activityInputMap.get(entry.getKey());
+            if (connectors != null) {
+                for (IConnectorDescriptor connector : connectors) {
+                    fromActivityId = jobActivityGraph.getProducerActivity(connector.getConnectorId());
+                    activity = activityMap.get(fromActivityId);
+                    fromFullClassName = activity.getClass().getName();
+                    fromClassName = fromFullClassName.substring(fromFullClassName.lastIndexOf('.') + 1);
+                    fromNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(fromActivityId.toString()),
+                            DotFormatBuilder.StringValue.of(fromActivityId.toString() + "-" + fromClassName));
+                    Pair<ActivityId, ActivityId> newPair = new ImmutablePair<>(fromActivityId, toActivityId);
+                    if (!activitiesPairedSet.contains(newPair)) {
+                        activitiesPairedSet.add(newPair);
+                        DotFormatBuilder.Edge edge = graphBuilder.createEdge(fromNode, toNode);
+                        if (connector.allProducersToAllConsumers()) {
+                            edge.setDashed().setColor(DotFormatBuilder.Color.BLUE);
+                        }
+                    }
+                }
+            }
+
+            // process from activity -> output
+            fromActivityId = toActivityId;
+            fromNode = toNode;
+            connectors = activityOutputMap.get(entry.getKey());
+            if (connectors != null) {
+                for (IConnectorDescriptor connector : connectors) {
+                    toActivityId = jobActivityGraph.getConsumerActivity(connector.getConnectorId());
+                    activity = activityMap.get(toActivityId);
+                    toFullClassName = activity.getClass().getName();
+                    toClassName = toFullClassName.substring(toFullClassName.lastIndexOf('.') + 1);
+                    toNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(toActivityId.toString()),
+                            DotFormatBuilder.StringValue.of(toActivityId.toString() + "-" + toClassName));
+                    Pair<ActivityId, ActivityId> newPair = new ImmutablePair<>(fromActivityId, toActivityId);
+                    if (!activitiesPairedSet.contains(newPair)) {
+                        activitiesPairedSet.add(newPair);
+                        DotFormatBuilder.Edge edge = graphBuilder.createEdge(fromNode, toNode);
+                        if (connector.allProducersToAllConsumers()) {
+                            edge.setDashed().setColor(DotFormatBuilder.Color.BLUE);
+                        }
+                    }
+                }
+            }
+        }
+
+        final Map<ActivityId, Set<ActivityId>> blocked2BlockerMap = jobActivityGraph.getBlocked2BlockerMap();
+        IActivity blockedActivity;
+        for (Map.Entry<ActivityId, Set<ActivityId>> entry : blocked2BlockerMap.entrySet()) {
+            blockedActivity = activityMap.get(entry.getKey());
+            toFullClassName = blockedActivity.getClass().getName();
+            toClassName = toFullClassName.substring(toFullClassName.lastIndexOf('.') + 1);
+            toActivityId = entry.getKey();
+            toNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(toActivityId.toString()),
+                    DotFormatBuilder.StringValue.of(toActivityId.toString() + "-" + toClassName));
+            for (ActivityId blockingActivityId : entry.getValue()) {
+                fromActivityId = blockingActivityId;
+                activity = activityMap.get(fromActivityId);
+                fromFullClassName = activity.getClass().getName();
+                fromClassName = fromFullClassName.substring(fromFullClassName.lastIndexOf('.') + 1);
+                fromNode = graphBuilder.createNode(DotFormatBuilder.StringValue.of(fromActivityId.toString()),
+                        DotFormatBuilder.StringValue.of(fromActivityId.toString() + "-" + fromClassName));
+                Pair<ActivityId, ActivityId> newPair = new ImmutablePair<>(fromActivityId, toActivityId);
+                if (!activitiesPairedSet.contains(newPair)) {
+                    activitiesPairedSet.add(newPair);
+                    graphBuilder.createEdge(fromNode, toNode).setColor(DotFormatBuilder.Color.RED);
+                }
+            }
+        }
+
+        return graphBuilder.getDotDocument();
+    }
+
+    /**
+     * Generates DOT format plan for {@link JobSpecification} that can be visualized using any DOT format visualizer.
+     *
+     * @param jobSpecification The job specification
+     * @return DOT format plan
+     */
+    public static String generate(final JobSpecification jobSpecification) {
+        final DotFormatBuilder graphBuilder = new DotFormatBuilder(DotFormatBuilder.StringValue.of("JobSpecification"));
+        final Map<ConnectorDescriptorId, IConnectorDescriptor> connectorMap = jobSpecification.getConnectorMap();
+        final Set<Constraint> constraints = jobSpecification.getUserConstraints();
+        Map<ConnectorDescriptorId, Pair<Pair<IOperatorDescriptor, Integer>, Pair<IOperatorDescriptor, Integer>>> cOp =
+                jobSpecification.getConnectorOperatorMap();
+        cOp.forEach((connId, srcAndDest) -> addToGraph(graphBuilder, constraints, connectorMap, connId, srcAndDest));
+        return graphBuilder.getDotDocument();
+    }
+
+    private static void addToGraph(DotFormatBuilder graph, Set<Constraint> constraints,
+            Map<ConnectorDescriptorId, IConnectorDescriptor> connMap, ConnectorDescriptorId connId,
+            Pair<Pair<IOperatorDescriptor, Integer>, Pair<IOperatorDescriptor, Integer>> srcAndDest) {
+        IConnectorDescriptor connector = connMap.get(connId);
+        String edgeLabel;
+        edgeLabel = connector.getClass().getName().substring(connector.getClass().getName().lastIndexOf(".") + 1);
+        edgeLabel += "-" + connId;
+        IOperatorDescriptor sourceOp = srcAndDest.getLeft().getLeft();
+        IOperatorDescriptor destOp = srcAndDest.getRight().getLeft();
+        StringBuilder source = new StringBuilder(
+                sourceOp.getClass().getName().substring(sourceOp.getClass().getName().lastIndexOf(".") + 1));
+        StringBuilder destination = new StringBuilder(
+                destOp.getClass().getName().substring(destOp.getClass().getName().lastIndexOf(".") + 1));
+        // constraints
+        for (Constraint constraint : constraints) {
+            LValueConstraintExpression lvalue = constraint.getLValue();
+            if (lvalue.getTag() == ConstraintExpression.ExpressionTag.PARTITION_COUNT) {
+                PartitionCountExpression count = (PartitionCountExpression) lvalue;
+                if (count.getOperatorDescriptorId().equals(sourceOp.getOperatorId())) {
+                    source.append("\n").append(constraint);
+                }
+                if (count.getOperatorDescriptorId().equals(destOp.getOperatorId())) {
+                    destination.append("\n").append(constraint);
+                }
+            } else if (lvalue.getTag() == ConstraintExpression.ExpressionTag.PARTITION_LOCATION) {
+                PartitionLocationExpression location = (PartitionLocationExpression) lvalue;
+                if (location.getOperatorDescriptorId().equals(sourceOp.getOperatorId())) {
+                    source.append("\n").append(constraint);
+                }
+                if (location.getOperatorDescriptorId().equals(destOp.getOperatorId())) {
+                    destination.append("\n").append(constraint);
+                }
+            }
+        }
+        DotFormatBuilder.Node sourceNode =
+                graph.createNode(DotFormatBuilder.StringValue.of(sourceOp.getOperatorId().toString()),
+                        DotFormatBuilder.StringValue.of(sourceOp.toString() + "-" + source));
+        DotFormatBuilder.Node destinationNode =
+                graph.createNode(DotFormatBuilder.StringValue.of(destOp.getOperatorId().toString()),
+                        DotFormatBuilder.StringValue.of(destOp.toString() + "-" + destination));
+        graph.createEdge(sourceNode, destinationNode).setLabel(DotFormatBuilder.StringValue.of(edgeLabel));
+    }
+}