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]