Changeset: 985acf30fee6 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/985acf30fee6
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 (time type)
diffs (288 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
@@ -24,15 +24,20 @@ statement ok
CREATE TABLE time_table(d TIME)
statement ok rowcount 1
-INSERT INTO time_table VALUES (cast('12:00:00' AS TIME))
+INSERT INTO time_table VALUES (cast('12:00:00.000001' AS TIME))
statement ok
-CREATE FUNCTION pyapi_time(d TIME) RETURNS STRING LANGUAGE PYTHON { return d; }
+CREATE FUNCTION pyapi_time(d TIME) RETURNS TIME LANGUAGE PYTHON { return d; }
+
+query T rowsort
+SELECT pyapi_time(cast('12:00:00.000001' AS TIME))
+----
+12:00:00.000001
query T rowsort
SELECT pyapi_time(d) FROM time_table
----
-12:00:00.000000
+12:00:00.000001
statement ok
CREATE TABLE timestamp_table(d TIMESTAMP)
@@ -81,8 +86,9 @@ statement ok
CREATE FUNCTION pyapi_ret_time() RETURNS TABLE(d TIME)
LANGUAGE PYTHON
{
+ import datetime
result = dict()
- result['d'] = '12:00:00'
+ result['d'] = datetime.time(12, 0, 0, 0)
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
@@ -78,6 +78,15 @@ PyObject *PyArrayObject_FromScalar(PyInp
/* error checking */
break;
}
+ 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_str:
vararray = PyUnicode_FromString(*((char
**)inp->dataptr));
break;
@@ -269,6 +278,27 @@ PyObject *PyArrayObject_FromBAT(PyInput
bat_iterator_end(&li);
break;
}
+ case TYPE_daytime: {
+ 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 daytime* dt = (const
daytime*)BUNtail(li, p);
+ data[j++] =
PyTime_FromTime(daytime_hour(*dt),
+
daytime_min(*dt),
+
daytime_sec(*dt),
+
daytime_usec(*dt));
+ }
+ }
+ bat_iterator_end(&li);
+ break;
+ }
case TYPE_str: {
bool unicode = false;
li = bat_iterator(b);
@@ -863,8 +893,10 @@ BAT *PyObject_ConvertToBAT(PyReturn *ret
switch (GetSQLType(type)) {
case EC_TIMESTAMP:
+ bat_type = TYPE_str;
+ break;
case EC_TIME:
- bat_type = TYPE_str;
+ bat_type = TYPE_daytime;
break;
case EC_DATE:
bat_type = TYPE_date;
@@ -1023,6 +1055,9 @@ BAT *PyObject_ConvertToBAT(PyReturn *ret
case TYPE_date:
NP_CREATE_BAT(b, date);
break;
+ case TYPE_daytime:
+ NP_CREATE_BAT(b, daytime);
+ break;
case TYPE_str: {
bool *mask = NULL;
char *data = NULL;
@@ -1084,7 +1119,7 @@ bit ConvertableSQLType(sql_subtype *sql_
{
switch (GetSQLType(sql_subtype)) {
/* case EC_DATE: */
- case EC_TIME:
+ /* case EC_TIME: */
case EC_TIMESTAMP:
case EC_DEC:
return 1;
@@ -1111,8 +1146,8 @@ str ConvertFromSQLType(BAT *b, sql_subty
assert(sql_subtype->type);
switch (sql_subtype->type->eclass) {
- case EC_DATE:
- case EC_TIME:
+ /* case EC_DATE: */
+ /* case EC_TIME: */
case EC_TIMESTAMP:
conv_type = TYPE_str;
break;
@@ -1267,6 +1302,7 @@ bit IsStandardBATType(int type)
case TYPE_hge:
#endif
case TYPE_date:
+ case TYPE_daytime:
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
@@ -66,6 +66,7 @@
#define nancheck_hge(bat) ((void)0) /* not used if no HAVE_HGE */
#define nancheck_oid(bat) ((void)0)
#define nancheck_date(bat) ((void)0)
+#define nancheck_daytime(bat) ((void)0)
#if defined(HAVE_FORK)
#define CREATE_BAT_ZEROCOPY(bat, mtpe, batstore)
\
{
\
@@ -550,8 +551,8 @@ convert_and_append(BAT* b, const char* t
((PyObject
**)&data[(index_offset * ret->count + iu) * \
ret->memory_size]), \
utf8_size, &utf8_string);
\
- if (msg != MAL_SUCCEED)
\
- goto wrapup;
\
+ if (msg != MAL_SUCCEED)
\
+ goto wrapup;
\
if (convert_and_append(b, utf8_string,
false) != GDK_SUCCEED) { \
msg = createException(MAL,
"pyapi3.eval", \
SQLSTATE(PY000) "BUNappend failed.\n"); \
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
@@ -279,7 +279,8 @@ bool PyType_IsPyScalar(PyObject *object)
return (PyArray_CheckScalar(object) || PyLong_Check(object) ||
PyFloat_Check(object) || PyUnicode_Check(object) ||
PyBool_Check(object) || PyByteArray_Check(object) ||
- PyBytes_Check(object) || PyDate_Check(object));
+ PyBytes_Check(object) || PyDate_Check(object) ||
+ PyTime_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
@@ -50,6 +50,10 @@ str pyobject_to_date(PyObject **ptr, siz
str str_to_date(const char *ptr, size_t maxsize, date *value);
str unicode_to_date(Py_UNICODE *ptr, size_t maxsize, date *value);
+str pyobject_to_daytime(PyObject **ptr, size_t maxsize, daytime *value);
+str str_to_daytime(const char *ptr, size_t maxsize, daytime *value);
+str unicode_to_daytime(Py_UNICODE *ptr, size_t maxsize, daytime *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
@@ -93,6 +93,32 @@ str pyobject_to_date(PyObject **ptr, siz
return msg;
}
+str pyobject_to_daytime(PyObject **ptr, size_t maxsize, daytime *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(PyTime_Check(*ptr)) {
+ *value = daytime_create(PyDateTime_TIME_GET_HOUR(*ptr),
+
PyDateTime_TIME_GET_MINUTE(*ptr),
+
PyDateTime_TIME_GET_SECOND(*ptr),
+
PyDateTime_TIME_GET_MICROSECOND(*ptr));
+ }
+ else {
+ msg = createException(MAL, "pyapi3.eval", "Invalid PyTime
object.");
+ }
+
+ wrapup:
+ return msg;
+}
+
+
str pyobject_to_blob(PyObject **ptr, size_t maxsize, blob **value) {
size_t size;
char* bytes_data;
@@ -211,41 +237,41 @@ wrapup:
str str_to_date(const char *ptr, size_t maxsize, date *value)
{
- if (ptr) {
- if (date_fromstr(ptr, &maxsize, &value, true) < 0) {
- return createException(MAL, "pyapi3.eval",
-
SQLSTATE(PY000) "Could not convert string %s to date.",
- ptr);
- }
- }
- else
- return createException(MAL, "pyapi3.eval",
- SQLSTATE(PY000)
"Invalid PyObject");
+ (void)ptr;
+ (void)maxsize;
+ (void)value;
- return MAL_SUCCEED;
+ return GDKstrdup("Implicit conversion of date to string is not
allowed.");
}
str unicode_to_date(Py_UNICODE *ptr, size_t maxsize, date *value)
{
- if (ptr) {
- const char *buf = PyUnicode_AsUTF8((PyObject *)ptr);
- if (buf == NULL || !PyUnicode_CheckExact(ptr)) {
- return createException(MAL, "pyapi3.pyapi",
-
SQLSTATE(PY000) "Invalid UTF-8 when converting to date.");
- }
- if (date_fromstr(buf, &maxsize, &value, true) < 0) {
- return createException(MAL, "pyapi3.eval",
-
SQLSTATE(PY000) "Could not convert string to date.");
- }
- }
- else
- return createException(MAL, "pyapi3.eval",
- SQLSTATE(PY000)
"Invalid PyObject");
+ (void)ptr;
+ (void)maxsize;
+ (void)value;
+
+ return GDKstrdup("Implicit conversion of date to string is not
allowed.");
+}
+
+str str_to_daytime(const char *ptr, size_t maxsize, daytime *value)
+{
+ (void)ptr;
+ (void)maxsize;
+ (void)value;
+ return GDKstrdup("Implicit conversion of time to string is not
allowed.");
+}
- return MAL_SUCCEED;
+str unicode_to_daytime(Py_UNICODE *ptr, size_t maxsize, daytime *value)
+{
+ (void)ptr;
+ (void)maxsize;
+ (void)value;
+
+ return GDKstrdup("Implicit conversion of time to string is not
allowed.");
}
+
#define PY_TO_(type, inttpe) \
str pyobject_to_##type(PyObject **pyobj, size_t maxsize, type *value) \
{ \
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]