Changeset: 70d80b1021de for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/70d80b1021de
Modified Files:
        sql/backends/monet5/UDF/pyapi3/Tests/pyapi3_18.test
        sql/backends/monet5/UDF/pyapi3/conversion3.c
        sql/backends/monet5/UDF/pyapi3/convert_loops.h
        sql/backends/monet5/UDF/pyapi3/pytypes3.c
        sql/backends/monet5/UDF/pyapi3/type_conversion.h
        sql/backends/monet5/UDF/pyapi3/type_conversion3.c
Branch: default
Log Message:

Add test and fix for issue #7289 (datetime type)


diffs (287 lines):

diff --git a/sql/backends/monet5/UDF/pyapi3/Tests/pyapi3_18.test 
b/sql/backends/monet5/UDF/pyapi3/Tests/pyapi3_18.test
--- a/sql/backends/monet5/UDF/pyapi3/Tests/pyapi3_18.test
+++ b/sql/backends/monet5/UDF/pyapi3/Tests/pyapi3_18.test
@@ -43,15 +43,21 @@ statement ok
 CREATE TABLE timestamp_table(d TIMESTAMP)
 
 statement ok rowcount 1
-INSERT INTO timestamp_table VALUES (cast('2000-1-1 12:00:00' AS TIMESTAMP))
+INSERT INTO timestamp_table VALUES (cast('2000-1-1 12:00:00.000001' AS 
TIMESTAMP))
 
 statement ok
-CREATE FUNCTION pyapi_timestamp(d TIMESTAMP) RETURNS STRING LANGUAGE PYTHON { 
return d; }
+CREATE FUNCTION pyapi_timestamp(d TIMESTAMP) RETURNS TIMESTAMP LANGUAGE PYTHON 
{ return d; }
+
+query T rowsort
+SELECT pyapi_timestamp(cast('2000-1-1 12:00:00.000001' AS TIMESTAMP)) FROM 
timestamp_table
+----
+2000-01-01 12:00:00.000001
 
 query T rowsort
 SELECT pyapi_timestamp(d) FROM timestamp_table
 ----
-2000-01-01 12:00:00.000000
+2000-01-01 12:00:00.000001
+
 
 statement ok
 CREATE TABLE decimal_table(d DECIMAL(10, 3))
@@ -101,8 +107,9 @@ statement ok
 CREATE FUNCTION pyapi_ret_timestamp() RETURNS TABLE(d TIMESTAMP)
 LANGUAGE PYTHON
 {
+    import datetime
     result = dict()
-    result['d'] = '2000-1-1 12:00:00'
+    result['d'] = datetime.datetime(2000, 1, 1, 12, 0, 0, 1)
     return result
 }
 
diff --git a/sql/backends/monet5/UDF/pyapi3/conversion3.c 
b/sql/backends/monet5/UDF/pyapi3/conversion3.c
--- a/sql/backends/monet5/UDF/pyapi3/conversion3.c
+++ b/sql/backends/monet5/UDF/pyapi3/conversion3.c
@@ -70,23 +70,29 @@ PyObject *PyArrayObject_FromScalar(PyInp
                        vararray = PyLong_FromHge(*((hge *)inp->dataptr));
                        break;
 #endif
-               case TYPE_date:
-                       {
+               case TYPE_date: {
                                USE_DATETIME_API;
                                date dt = *(date *)inp->dataptr;
                                vararray = PyDate_FromDate(date_year(dt), 
date_month(dt), date_day(dt));
                                /* error checking */
                                break;
-                       }
-               case TYPE_daytime:
-                       {
+               }
+               case TYPE_daytime: {
                                USE_DATETIME_API;
                                daytime dt = *(daytime *)inp->dataptr;
                                vararray = PyTime_FromTime(daytime_hour(dt), 
daytime_min(dt), daytime_sec(dt), daytime_usec(dt));
                                /* error checking */
                                break;
-                       }
-
+               }
+               case TYPE_timestamp: {
+                               USE_DATETIME_API;
+                               timestamp ts = *(timestamp *)inp->dataptr;
+                               date dt = timestamp_date(ts);
+                               daytime dtm = timestamp_daytime(ts);
+                               vararray = 
PyDateTime_FromDateAndTime(date_year(dt), date_month(dt), date_day(dt), 
daytime_hour(dtm), daytime_min(dtm), daytime_sec(dtm), daytime_usec(dtm));
+                               /* error checking */
+                               break;
+               }
                case TYPE_str:
                        vararray = PyUnicode_FromString(*((char 
**)inp->dataptr));
                        break;
@@ -299,6 +305,28 @@ PyObject *PyArrayObject_FromBAT(PyInput 
                                bat_iterator_end(&li);
                                break;
                        }
+                       case TYPE_timestamp: {
+                               li = bat_iterator(b);
+
+                               USE_DATETIME_API;
+                               vararray = PyArray_EMPTY(1, elements, 
NPY_OBJECT, 0);
+                               {
+                                       PyObject **data = ((PyObject 
**)PyArray_DATA((PyArrayObject *)vararray));
+                                       // PyObject *obj;
+                                       j = 0;
+                                       BATloop(b, p, q)
+                                       {
+                                               const timestamp* ts = (const 
timestamp*)BUNtail(li, p);
+                                               const date dt = 
timestamp_date(*ts);
+                                               const daytime dtm = 
timestamp_daytime(*ts);
+
+                                               data[j++] = 
PyDateTime_FromDateAndTime(date_year(dt), date_month(dt), date_day(dt), 
daytime_hour(dtm), daytime_min(dtm), daytime_sec(dtm), daytime_usec(dtm));
+                                       }
+                               }
+                               bat_iterator_end(&li);
+                               break;
+                       }
+
                        case TYPE_str: {
                                bool unicode = false;
                                li = bat_iterator(b);
@@ -893,7 +921,7 @@ BAT *PyObject_ConvertToBAT(PyReturn *ret
 
        switch (GetSQLType(type)) {
                case EC_TIMESTAMP:
-                       bat_type = TYPE_str;
+                       bat_type = TYPE_timestamp;
                        break;
                case EC_TIME:
                        bat_type = TYPE_daytime;
@@ -1058,6 +1086,9 @@ BAT *PyObject_ConvertToBAT(PyReturn *ret
                        case TYPE_daytime:
                                NP_CREATE_BAT(b, daytime);
                                break;
+                       case TYPE_timestamp:
+                               NP_CREATE_BAT(b, timestamp);
+                               break;
                        case TYPE_str: {
                                bool *mask = NULL;
                                char *data = NULL;
@@ -1120,7 +1151,7 @@ bit ConvertableSQLType(sql_subtype *sql_
        switch (GetSQLType(sql_subtype)) {
                /* case EC_DATE: */
                /* case EC_TIME: */
-               case EC_TIMESTAMP:
+               /* case EC_TIMESTAMP: */
                case EC_DEC:
                        return 1;
        }
@@ -1148,9 +1179,9 @@ str ConvertFromSQLType(BAT *b, sql_subty
        switch (sql_subtype->type->eclass) {
                /* case EC_DATE: */
                /* case EC_TIME: */
-               case EC_TIMESTAMP:
-                       conv_type = TYPE_str;
-                       break;
+               /* case EC_TIMESTAMP: */
+               /*      conv_type = TYPE_str; */
+               /*      break; */
                case EC_DEC:
                        conv_type = TYPE_dbl;
                        break;
@@ -1303,6 +1334,7 @@ bit IsStandardBATType(int type)
 #endif
                case TYPE_date:
                case TYPE_daytime:
+               case TYPE_timestamp:
                case TYPE_str:
                        return 1;
                default:
diff --git a/sql/backends/monet5/UDF/pyapi3/convert_loops.h 
b/sql/backends/monet5/UDF/pyapi3/convert_loops.h
--- a/sql/backends/monet5/UDF/pyapi3/convert_loops.h
+++ b/sql/backends/monet5/UDF/pyapi3/convert_loops.h
@@ -67,6 +67,7 @@
 #define nancheck_oid(bat) ((void)0)
 #define nancheck_date(bat) ((void)0)
 #define nancheck_daytime(bat) ((void)0)
+#define nancheck_timestamp(bat) ((void)0)
 #if defined(HAVE_FORK)
 #define CREATE_BAT_ZEROCOPY(bat, mtpe, batstore)                               
\
        {                                                                       
   \
diff --git a/sql/backends/monet5/UDF/pyapi3/pytypes3.c 
b/sql/backends/monet5/UDF/pyapi3/pytypes3.c
--- a/sql/backends/monet5/UDF/pyapi3/pytypes3.c
+++ b/sql/backends/monet5/UDF/pyapi3/pytypes3.c
@@ -280,7 +280,7 @@ bool PyType_IsPyScalar(PyObject *object)
                        PyFloat_Check(object) || PyUnicode_Check(object) ||
                        PyBool_Check(object) || PyByteArray_Check(object) ||
                        PyBytes_Check(object) || PyDate_Check(object) ||
-                       PyTime_Check(object));
+                       PyTime_Check(object) || PyDateTime_Check(object));
 }
 
 void _pytypes_init(void) { _import_array(); }
diff --git a/sql/backends/monet5/UDF/pyapi3/type_conversion.h 
b/sql/backends/monet5/UDF/pyapi3/type_conversion.h
--- a/sql/backends/monet5/UDF/pyapi3/type_conversion.h
+++ b/sql/backends/monet5/UDF/pyapi3/type_conversion.h
@@ -54,6 +54,11 @@ str pyobject_to_daytime(PyObject **ptr, 
 str str_to_daytime(const char *ptr, size_t maxsize, daytime *value);
 str unicode_to_daytime(Py_UNICODE *ptr, size_t maxsize, daytime *value);
 
+str pyobject_to_timestamp(PyObject **ptr, size_t maxsize, timestamp *value);
+str str_to_timestamp(const char *ptr, size_t maxsize, timestamp *value);
+str unicode_to_timestamp(Py_UNICODE *ptr, size_t maxsize, timestamp *value);
+
+
 //using macros, create a number of str_to_<type>, unicode_to_<type> and 
pyobject_to_<type> functions (we are Java now)
 #define CONVERSION_FUNCTION_HEADER_FACTORY(tpe)          \
     str str_to_##tpe(const char *ptr, size_t maxsize, tpe *value);          \
diff --git a/sql/backends/monet5/UDF/pyapi3/type_conversion3.c 
b/sql/backends/monet5/UDF/pyapi3/type_conversion3.c
--- a/sql/backends/monet5/UDF/pyapi3/type_conversion3.c
+++ b/sql/backends/monet5/UDF/pyapi3/type_conversion3.c
@@ -118,6 +118,34 @@ str pyobject_to_daytime(PyObject **ptr, 
        return msg;
 }
 
+str pyobject_to_timestamp(PyObject **ptr, size_t maxsize, timestamp *value) {
+       str msg = MAL_SUCCEED;
+
+       if (ptr == NULL || *ptr == NULL) {
+               msg = createException(MAL, "pyapi3.eval", "Invalid PyObject.");
+               goto wrapup;
+       }
+
+       (void) maxsize;
+
+       USE_DATETIME_API;
+       if(PyDateTime_Check(*ptr)) {
+               date dt = date_create(PyDateTime_GET_YEAR(*ptr),
+                                                         
PyDateTime_GET_MONTH(*ptr),
+                                                         
PyDateTime_GET_DAY(*ptr));
+               daytime dtm = daytime_create(PyDateTime_DATE_GET_HOUR(*ptr),
+                                                                        
PyDateTime_DATE_GET_MINUTE(*ptr),
+                                                                        
PyDateTime_DATE_GET_SECOND(*ptr),
+                                                                        
PyDateTime_DATE_GET_MICROSECOND(*ptr));
+               *value = timestamp_create(dt, dtm);
+       }
+       else {
+               msg = createException(MAL, "pyapi3.eval", "Invalid PyDateTime 
object.");
+       }
+
+ wrapup:
+       return msg;
+}
 
 str pyobject_to_blob(PyObject **ptr, size_t maxsize, blob **value) {
        size_t size;
@@ -241,7 +269,7 @@ str str_to_date(const char *ptr, size_t 
        (void)maxsize;
        (void)value;
 
-       return GDKstrdup("Implicit conversion of date to string is not 
allowed.");
+       return GDKstrdup("Implicit conversion of string to date is not 
allowed.");
 }
 
 str unicode_to_date(Py_UNICODE *ptr, size_t maxsize, date *value)
@@ -250,7 +278,7 @@ str unicode_to_date(Py_UNICODE *ptr, siz
        (void)maxsize;
        (void)value;
 
-       return GDKstrdup("Implicit conversion of date to string is not 
allowed.");
+       return GDKstrdup("Implicit conversion of string to date is not 
allowed.");
 }
 
 str str_to_daytime(const char *ptr, size_t maxsize, daytime *value)
@@ -259,7 +287,7 @@ str str_to_daytime(const char *ptr, size
        (void)maxsize;
        (void)value;
 
-       return GDKstrdup("Implicit conversion of time to string is not 
allowed.");
+       return GDKstrdup("Implicit conversion of string to daytime is not 
allowed.");
 }
 
 str unicode_to_daytime(Py_UNICODE *ptr, size_t maxsize, daytime *value)
@@ -268,7 +296,25 @@ str unicode_to_daytime(Py_UNICODE *ptr, 
        (void)maxsize;
        (void)value;
 
-       return GDKstrdup("Implicit conversion of time to string is not 
allowed.");
+       return GDKstrdup("Implicit conversion of string to daytime is not 
allowed.");
+}
+
+str str_to_timestamp(const char *ptr, size_t maxsize, timestamp *value)
+{
+       (void)ptr;
+       (void)maxsize;
+       (void)value;
+
+       return GDKstrdup("Implicit conversion of string to timestamp is not 
allowed.");
+}
+
+str unicode_to_timestamp(Py_UNICODE *ptr, size_t maxsize, timestamp *value)
+{
+       (void)ptr;
+       (void)maxsize;
+       (void)value;
+
+       return GDKstrdup("Implicit conversion of string to timestamp is not 
allowed.");
 }
 
 
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to