gfphoenix78 commented on code in PR #901:
URL: https://github.com/apache/cloudberry/pull/901#discussion_r2123382436


##########
contrib/try_convert/try_convert.c:
##########
@@ -0,0 +1,446 @@
+#include "postgres.h"
+
+#include "catalog/pg_cast.h"
+#include "utils/syscache.h"
+#include "utils/lsyscache.h"
+#include "nodes/nodeFuncs.h"
+// #include "nodes/miscnodes.h"
+
+#include "executor/spi.h"
+
+#include "funcapi.h"
+
+#define USE_PG_TRY_CATCH
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(try_convert);
+
+
+typedef enum ConversionType
+{
+       CONVERSION_TYPE_FUNC,
+       CONVERSION_TYPE_RELABEL,
+       CONVERSION_TYPE_VIA_IO,
+       CONVERSION_TYPE_ARRAY,  
+    CONVERSION_TYPE_NONE       
+} ConversionType;
+
+
+ConversionType find_conversion_way(Oid targetTypeId, Oid sourceTypeId, Oid 
*funcId);
+ConversionType find_typmod_conversion_function(Oid typeId, Oid *funcId);
+Datum convert_from_function(Datum value, int32 typmod, Oid funcId, bool 
*is_failed);
+Datum convert_via_io(Datum value, Oid sourceTypeId, Oid targetTypeId, int32 
targetTypMod, bool *is_failed);
+int32 get_call_expr_argtypmod(Node *expr, int argnum);
+Oid get_fn_expr_argtypmod(FmgrInfo *flinfo, int argnum);
+Datum convert(Datum value, ConversionType conversion_type, Oid funcId, Oid 
sourceTypeId, Oid targetTypeId, int32 targetTypMod, bool *is_failed);
+Datum convert_type_typmod(Datum value, int32 sourceTypMod, Oid targetTypeId, 
int32 targetTypMod, bool *is_failed);
+
+
+ConversionType
+find_conversion_way(Oid targetTypeId, Oid sourceTypeId, Oid *funcId)
+{
+       ConversionType result = CONVERSION_TYPE_NONE;
+       HeapTuple       tuple;
+
+       *funcId = InvalidOid;
+
+       /* Perhaps the types are domains; if so, look at their base types */
+       if (OidIsValid(sourceTypeId))
+               sourceTypeId = getBaseType(sourceTypeId);
+       if (OidIsValid(targetTypeId))
+               targetTypeId = getBaseType(targetTypeId);
+
+       /* Domains are always coercible to and from their base type */
+       if (sourceTypeId == targetTypeId)
+               return CONVERSION_TYPE_RELABEL;
+
+       /* SELECT castcontext from pg_cast */
+
+       /* Look in pg_cast */
+       tuple = SearchSysCache2(CASTSOURCETARGET,
+                                                       
ObjectIdGetDatum(sourceTypeId),
+                                                       
ObjectIdGetDatum(targetTypeId));
+
+       if (HeapTupleIsValid(tuple))
+       {
+               Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
+
+        switch (castForm->castmethod)
+        {
+            case COERCION_METHOD_FUNCTION:
+                *funcId = castForm->castfunc;
+                result = CONVERSION_TYPE_FUNC;
+                break;
+            case COERCION_METHOD_INOUT:
+                result = CONVERSION_TYPE_VIA_IO;
+                break;
+            case COERCION_METHOD_BINARY:
+                result = CONVERSION_TYPE_RELABEL;
+                break;
+            default:
+                elog(ERROR, "unrecognized castmethod: %d",
+                        (int) castForm->castmethod);
+                break;
+        }
+       
+
+               ReleaseSysCache(tuple);
+       }
+       else
+       {
+               /*
+                * If there's no pg_cast entry, perhaps we are dealing with a 
pair of
+                * array types.  If so, and if the element types have a 
suitable cast,
+                * report that we can coerce with an ArrayCoerceExpr.
+                *
+                * Note that the source type can be a domain over array, but 
not the
+                * target, because ArrayCoerceExpr won't check domain 
constraints.
+                *
+                * Hack: disallow coercions to oidvector and int2vector, which
+                * otherwise tend to capture coercions that should go to "real" 
array
+                * types.  We want those types to be considered "real" arrays 
for many
+                * purposes, but not this one.  (Also, ArrayCoerceExpr isn't
+                * guaranteed to produce an output that meets the restrictions 
of
+                * these datatypes, such as being 1-dimensional.)
+                */
+               if (targetTypeId != OIDVECTOROID && targetTypeId != 
INT2VECTOROID)
+               {
+                       Oid                     targetElem;
+                       Oid                     sourceElem;
+
+                       if ((targetElem = get_element_type(targetTypeId)) != 
InvalidOid &&
+                       (sourceElem = get_base_element_type(sourceTypeId)) != 
InvalidOid)
+                       {
+                               ConversionType elempathtype;
+                               Oid                        elemfuncid;
+
+                               elempathtype = find_conversion_way(targetElem,
+                                                                               
                   sourceElem,
+                                                                               
                  &elemfuncid);
+                               if (elempathtype != CONVERSION_TYPE_NONE &&
+                                       elempathtype != CONVERSION_TYPE_ARRAY)
+                               {
+                                       *funcId = elemfuncid;
+                                       if (elempathtype == 
CONVERSION_TYPE_VIA_IO)
+                                               result = CONVERSION_TYPE_VIA_IO;
+                                       else
+                                               result = CONVERSION_TYPE_ARRAY;
+                               }
+                       }
+               }
+
+               /*
+                * If we still haven't found a possibility, consider automatic 
casting
+                * using I/O functions.  We allow assignment casts to string 
types and
+                * explicit casts from string types to be handled this way. (The
+                * CoerceViaIO mechanism is a lot more general than that, but 
this is
+                * all we want to allow in the absence of a pg_cast entry.) It 
would
+                * probably be better to insist on explicit casts in both 
directions,
+                * but this is a compromise to preserve something of the pre-8.3
+                * behavior that many types had implicit (yipes!) casts to text.
+                */
+               if (result == CONVERSION_TYPE_NONE)
+               {
+                       if (TypeCategory(targetTypeId) == TYPCATEGORY_STRING)
+                               result = CONVERSION_TYPE_VIA_IO;
+                       else if (TypeCategory(sourceTypeId) == 
TYPCATEGORY_STRING)
+                               result = CONVERSION_TYPE_VIA_IO;
+               }
+       }
+
+       return result;
+}
+
+ConversionType
+find_typmod_conversion_function(Oid typeId, Oid *funcId)
+{
+       ConversionType result;
+       HeapTuple       tuple;
+
+       *funcId = InvalidOid;
+       result = CONVERSION_TYPE_FUNC;
+
+       /* Look in pg_cast */
+       tuple = SearchSysCache2(CASTSOURCETARGET,
+                                                       
ObjectIdGetDatum(typeId),
+                                                       
ObjectIdGetDatum(typeId));
+
+       if (HeapTupleIsValid(tuple))
+       {
+               Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
+
+               *funcId = castForm->castfunc;
+               ReleaseSysCache(tuple);
+       }

Review Comment:
   Better add else branch here.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to