IMPALA-10175: Extend error msg when CAST(FORMAT) fails for DATE

The previous error message contained only the input string but
including the format string as well would make debugging easier.

Extended error message:
SELECT CAST('0;367' as date format 'YY;DDD');
String to Date parse failed. Input '0;367' doesn't match with
format 'YY;IDD'

Change-Id: I4e379f0f112e83e1511edb170bbe41f903972622
Reviewed-on: http://gerrit.cloudera.org:8080/16473
Tested-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
Reviewed-by: Zoltan Borok-Nagy <boroknagyz@cloudera.com>
diff --git a/be/src/exprs/cast-functions-ir.cc b/be/src/exprs/cast-functions-ir.cc
index 84a899b..be46ad7 100644
--- a/be/src/exprs/cast-functions-ir.cc
+++ b/be/src/exprs/cast-functions-ir.cc
@@ -359,8 +359,15 @@
   }
   if (UNLIKELY(!dv.IsValid())) {
     string invalid_val = string(string_val, val.len);
-    ctx->SetError(Substitute("String to Date parse failed. Invalid string val: \"$0\"",
-        invalid_val).c_str());
+    string error_msg;
+    if (format_ctx == nullptr) {
+      error_msg = Substitute("String to Date parse failed. Invalid string val: '$0'",
+        invalid_val);
+    } else {
+      error_msg = Substitute("String to Date parse failed. Input '$0' doesn't match "
+        "with format '$1'", invalid_val, format_ctx->fmt);
+    }
+    ctx->SetError(error_msg.c_str());
     return DateVal::null();
   }
   return dv.ToDateVal();
diff --git a/testdata/workloads/functional-query/queries/QueryTest/date-partitioning.test b/testdata/workloads/functional-query/queries/QueryTest/date-partitioning.test
index 3574281..7570b33 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/date-partitioning.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/date-partitioning.test
@@ -74,12 +74,12 @@
 # When the implicit cast fails, insert fails with error
 insert into $DATABASE.dtbl partition(p) select * from $DATABASE.stbl where p='1400-01-01';
 ---- CATCH
-UDF ERROR: String to Date parse failed. Invalid string val: "400-01-4"
+UDF ERROR: String to Date parse failed. Invalid string val: '400-01-4'
 ====
 ---- QUERY
 insert into $DATABASE.dtbl partition(p) select * from $DATABASE.stbl where p='1400-01-';
 ---- CATCH
-UDF ERROR: String to Date parse failed. Invalid string val: "1400-01-"
+UDF ERROR: String to Date parse failed. Invalid string val: '1400-01-'
 ====
 ---- QUERY
 # Use dynamic partition specification in insert.
diff --git a/testdata/workloads/functional-query/queries/QueryTest/date.test b/testdata/workloads/functional-query/queries/QueryTest/date.test
index d6b47fb..6fcdfc2 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/date.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/date.test
@@ -102,7 +102,7 @@
 # Test < 0001 date handling during string to date conversion.
 select CAST("0000-01-01" AS DATE);
 ---- CATCH
-UDF ERROR: String to Date parse failed. Invalid string val: "0000-01-01"
+UDF ERROR: String to Date parse failed. Invalid string val: '0000-01-01'
 ====
 ---- QUERY
 # Test <1400 date handling during string to date conversion.
@@ -116,19 +116,19 @@
 # Test >=10000 date handling during string to date conversion.
 select CAST("10000-01-01" AS DATE);
 ---- CATCH
-UDF ERROR: String to Date parse failed. Invalid string val: "10000-01-01"
+UDF ERROR: String to Date parse failed. Invalid string val: '10000-01-01'
 ====
 ---- QUERY
 # Test leap year checking during string to date conversion.
 select CAST("1900-02-29" AS DATE);
 ---- CATCH
-UDF ERROR: String to Date parse failed. Invalid string val: "1900-02-29"
+UDF ERROR: String to Date parse failed. Invalid string val: '1900-02-29'
 ====
 ---- QUERY
 # Test invalid format handling during string to date conversion.
 select CAST("not a date" AS DATE);
 ---- CATCH
-UDF ERROR: String to Date parse failed. Invalid string val: "not a date"
+UDF ERROR: String to Date parse failed. Invalid string val: 'not a date'
 ====
 ---- QUERY
 # Test 0001-01-01 and 9999-12-31 date literal
@@ -594,7 +594,7 @@
 # STRING->DATE conversion fails because date string is invalid.
 select cast('not-a-date' as date);
 ---- CATCH
-UDF ERROR: String to Date parse failed. Invalid string val: "not-a-date"
+UDF ERROR: String to Date parse failed. Invalid string val: 'not-a-date'
 ====
 ---- QUERY
 # Basic test for FORMAT clause in CAST().
diff --git a/tests/query_test/test_cast_with_format.py b/tests/query_test/test_cast_with_format.py
index 504440c..2e51276 100644
--- a/tests/query_test/test_cast_with_format.py
+++ b/tests/query_test/test_cast_with_format.py
@@ -1455,6 +1455,12 @@
         r''' 'FXYYYY-"\\\'"-MM-DD') ''')
     assert result.data == ["2010-02-01"]
 
+    # Test error message where format contains text token with escaped double quote.
+    err = self.execute_query_expect_failure(self.client,
+        r'''select cast('1985-AB"CD11-23' as date format 'YYYY-"AB\"C"MM-DD')''')
+    assert (r'''String to Date parse failed. Input '1985-AB"CD11-23' doesn't match '''
+        r'''with format 'YYYY-"AB\"C"MM-DD''' in str(err))
+
   def test_iso8601_week_based_date_tokens(self):
     # Format 0001-01-01 and 9999-12-31 dates.
     # 0001-01-01 is Monday, belongs to the 1st week of year 1.
@@ -1474,10 +1480,12 @@
     # Year 9999 has 52 weeks. 9999-12-31 is Friday.
     err = self.execute_query_expect_failure(self.client,
         "select cast('9999/52/06' as date format 'IYYY/IW/ID')")
-    assert 'String to Date parse failed. Invalid string val: "9999/52/06"' in str(err)
+    assert (r'''String to Date parse failed. Input '9999/52/06' doesn't match with '''
+        r'''format 'IYYY/IW/ID''' in str(err))
     err = self.execute_query_expect_failure(self.client,
         "select cast('9999/53/01' as date format 'IYYY/IW/ID')")
-    assert 'String to Date parse failed. Invalid string val: "9999/53/01"' in str(err)
+    assert (r'''String to Date parse failed. Input '9999/53/01' doesn't match with '''
+        r'''format 'IYYY/IW/ID''' in str(err))
 
     # Format 1400-01-01 and 9999-12-31 timestamps.
     # 1400-01-01 is Wednesday, belongs to the 1st week of year 1400.
@@ -1529,7 +1537,8 @@
 
     err = self.execute_query_expect_failure(self.client,
         "select cast('2019/53/01' as date format 'IYYY/IW/ID')")
-    assert 'String to Date parse failed. Invalid string val: "2019/53/01"' in str(err)
+    assert (r'''String to Date parse failed. Input '2019/53/01' doesn't match with '''
+        r'''format 'IYYY/IW/ID''' in str(err))
 
     # Format 4, 3, 2, 1-digit week numbering year.
     # 2020-01-01 is Wednesday, belongs to week 1 of year 2020.
@@ -1670,7 +1679,8 @@
     assert result.data == ["NULL\tNULL\tNULL\tNULL\tNULL"]
     err = self.execute_query_expect_failure(self.client,
         "select cast('2015/3/05' as date format 'FXIYYY/IW/ID')")
-    assert 'String to Date parse failed. Invalid string val: "2015/3/05"' in str(err)
+    assert (r'''String to Date parse failed. Input '2015/3/05' doesn't match with '''
+        r'''format 'FXIYYY/IW/ID''' in str(err))
 
     query_options = dict({'now_string': '2019-01-01 11:11:11'})
     result = self.execute_query(