X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=psycopg2%2Fpsycopg%2Fadapter_mxdatetime.c;fp=psycopg2%2Fpsycopg%2Fadapter_mxdatetime.c;h=3b23148935edd87b75b36ae11efdebfc7ab66bbc;hb=e5bdc26e1423689c0ab3204931335787737946ea;hp=0000000000000000000000000000000000000000;hpb=f8dd312990da7cc744e1c148bfd395c18492f3f1;p=plcapi.git diff --git a/psycopg2/psycopg/adapter_mxdatetime.c b/psycopg2/psycopg/adapter_mxdatetime.c new file mode 100644 index 0000000..3b23148 --- /dev/null +++ b/psycopg2/psycopg/adapter_mxdatetime.c @@ -0,0 +1,446 @@ +/* adapter_mxdatetime.c - mx date/time objects + * + * Copyright (C) 2003-2004 Federico Di Gregorio + * + * This file is part of psycopg. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#define PSYCOPG_MODULE +#include "psycopg/config.h" +#include "psycopg/python.h" +#include "psycopg/psycopg.h" +#include "psycopg/adapter_mxdatetime.h" +#include "psycopg/microprotocols_proto.h" + +/* the pointer to the mxDateTime API is initialized by the module init code, + we just need to grab it */ +extern mxDateTimeModule_APIObject *mxDateTimeP; + + +/* mxdatetime_str, mxdatetime_getquoted - return result of quoting */ + +static PyObject * +mxdatetime_str(mxdatetimeObject *self) +{ + PyObject *str = NULL, *res = NULL; + + switch (self->type) { + + case PSYCO_MXDATETIME_DATE: + case PSYCO_MXDATETIME_TIMESTAMP: + str = PyObject_Str(self->wrapped); + + /* given the limitation of the mx.DateTime module that uses the same + type for both date and timestamp values we need to do some black + magic and make sure we're not using an adapt()ed timestamp as a + simple date */ + if (strncmp(&(PyString_AsString(str)[11]), "00:00:00.000", 12) == 0) { + PyObject *tmp = + PyString_FromStringAndSize(PyString_AsString(str), 10); + Py_DECREF(str); + str = tmp; + } + break; + + case PSYCO_MXDATETIME_TIME: + case PSYCO_MXDATETIME_INTERVAL: + str = PyObject_Str(self->wrapped); + + /* given the limitation of the mx.DateTime module that uses the same + type for both time and delta values we need to do some black magic + and make sure we're not using an adapt()ed interval as a simple + time */ + if (PyString_Size(str) > 8 && PyString_AsString(str)[8] == ':') { + mxDateTimeDeltaObject *obj = (mxDateTimeDeltaObject*)self->wrapped; + + char buffer[8]; + int i, j, x; + + double ss = obj->hour*3600.0 + obj->minute*60.0 + obj->second; + int us = (int)((ss - floor(ss))*1000000); + + for (i=1000000, j=0; i > 0 ; i /= 10) { + x = us/i; + us -= x*i; + buffer[j++] = '0'+x; + } + buffer[j] = '\0'; + + res = PyString_FromFormat("'%ld days %d.%s seconds'", + obj->day, (int)round(ss), buffer); + } + break; + } + + if (str != NULL && res == NULL) { + res = PyString_FromFormat("'%s'", PyString_AsString(str)); + } + Py_XDECREF(str); + + return res; +} + +PyObject * +mxdatetime_getquoted(mxdatetimeObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + return mxdatetime_str(self); +} + +PyObject * +mxdatetime_conform(mxdatetimeObject *self, PyObject *args) +{ + PyObject *res, *proto; + + if (!PyArg_ParseTuple(args, "O", &proto)) return NULL; + + if (proto == (PyObject*)&isqlquoteType) + res = (PyObject*)self; + else + res = Py_None; + + Py_INCREF(res); + return res; +} + +/** the MxDateTime object **/ + +/* object member list */ + +static struct PyMemberDef mxdatetimeObject_members[] = { + {"adapted", T_OBJECT, offsetof(mxdatetimeObject, wrapped), RO}, + {"type", T_INT, offsetof(mxdatetimeObject, type), RO}, + {NULL} +}; + +/* object method table */ + +static PyMethodDef mxdatetimeObject_methods[] = { + {"getquoted", (PyCFunction)mxdatetime_getquoted, METH_VARARGS, + "getquoted() -> wrapped object value as SQL date/time"}, + {"__conform__", (PyCFunction)mxdatetime_conform, METH_VARARGS, NULL}, + {NULL} /* Sentinel */ +}; + +/* initialization and finalization methods */ + +static int +mxdatetime_setup(mxdatetimeObject *self, PyObject *obj, int type) +{ + Dprintf("mxdatetime_setup: init mxdatetime object at %p, refcnt = %d", + self, ((PyObject *)self)->ob_refcnt); + + self->type = type; + self->wrapped = obj; + Py_INCREF(self->wrapped); + + Dprintf("mxdatetime_setup: good mxdatetime object at %p, refcnt = %d", + self, ((PyObject *)self)->ob_refcnt); + return 0; +} + +static void +mxdatetime_dealloc(PyObject* obj) +{ + mxdatetimeObject *self = (mxdatetimeObject *)obj; + + Py_XDECREF(self->wrapped); + + Dprintf("mxdatetime_dealloc: deleted mxdatetime object at %p, refcnt = %d", + obj, obj->ob_refcnt); + + obj->ob_type->tp_free(obj); +} + +static int +mxdatetime_init(PyObject *obj, PyObject *args, PyObject *kwds) +{ + PyObject *mx; + int type = -1; /* raise an error if type was not passed! */ + + if (!PyArg_ParseTuple(args, "O|i", &mx, &type)) + return -1; + + return mxdatetime_setup((mxdatetimeObject *)obj, mx, type); +} + +static PyObject * +mxdatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + return type->tp_alloc(type, 0); +} + +static void +mxdatetime_del(PyObject* self) +{ + PyObject_Del(self); +} + +static PyObject * +mxdatetime_repr(mxdatetimeObject *self) +{ + return PyString_FromFormat("", + self); +} + +/* object type */ + +#define mxdatetimeType_doc \ +"MxDateTime(mx, type) -> new mx.DateTime wrapper object" + +PyTypeObject mxdatetimeType = { + PyObject_HEAD_INIT(NULL) + 0, + "psycopg2._psycopg.MxDateTime", + sizeof(mxdatetimeObject), + 0, + mxdatetime_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + + 0, /*tp_compare*/ + (reprfunc)mxdatetime_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + + 0, /*tp_call*/ + (reprfunc)mxdatetime_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + + mxdatetimeType_doc, /*tp_doc*/ + + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + + /* Attribute descriptor and subclassing stuff */ + + mxdatetimeObject_methods, /*tp_methods*/ + mxdatetimeObject_members, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + + mxdatetime_init, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + mxdatetime_new, /*tp_new*/ + (freefunc)mxdatetime_del, /*tp_free Low-level free-memory routine */ + 0, /*tp_is_gc For PyObject_IS_GC */ + 0, /*tp_bases*/ + 0, /*tp_mro method resolution order */ + 0, /*tp_cache*/ + 0, /*tp_subclasses*/ + 0 /*tp_weaklist*/ +}; + + +/** module-level functions **/ + +#ifdef PSYCOPG_DEFAULT_MXDATETIME + +PyObject * +psyco_Date(PyObject *self, PyObject *args) +{ + PyObject *res, *mx; + int year, month, day; + + if (!PyArg_ParseTuple(args, "iii", &year, &month, &day)) + return NULL; + + mx = mxDateTimeP->DateTime_FromDateAndTime(year, month, day, 0, 0, 0.0); + if (mx == NULL) return NULL; + + res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_DATE); + Py_DECREF(mx); + return res; +} + +PyObject * +psyco_Time(PyObject *self, PyObject *args) +{ + PyObject *res, *mx; + int hours, minutes=0; + double seconds=0.0; + + if (!PyArg_ParseTuple(args, "iid", &hours, &minutes, &seconds)) + return NULL; + + mx = mxDateTimeP->DateTimeDelta_FromTime(hours, minutes, seconds); + if (mx == NULL) return NULL; + + res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_TIME); + Py_DECREF(mx); + return res; +} + +PyObject * +psyco_Timestamp(PyObject *self, PyObject *args) +{ + PyObject *res, *mx; + int year, month, day; + int hour=0, minute=0; /* default to midnight */ + double second=0.0; + + if (!PyArg_ParseTuple(args, "lii|iid", &year, &month, &day, + &hour, &minute, &second)) + return NULL; + + mx = mxDateTimeP->DateTime_FromDateAndTime(year, month, day, + hour, minute, second); + if (mx == NULL) return NULL; + + res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_TIMESTAMP); + Py_DECREF(mx); + return res; +} + +PyObject * +psyco_DateFromTicks(PyObject *self, PyObject *args) +{ + PyObject *res, *mx; + double ticks; + + if (!PyArg_ParseTuple(args,"d", &ticks)) + return NULL; + + if (!(mx = mxDateTimeP->DateTime_FromTicks(ticks))) + return NULL; + + res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_DATE); + Py_DECREF(mx); + return res; +} + +PyObject * +psyco_TimeFromTicks(PyObject *self, PyObject *args) +{ + PyObject *res, *mx, *dt; + double ticks; + + if (!PyArg_ParseTuple(args,"d", &ticks)) + return NULL; + + if (!(dt = mxDateTimeP->DateTime_FromTicks(ticks))) + return NULL; + + if (!(mx = mxDateTimeP->DateTimeDelta_FromDaysAndSeconds( + 0, ((mxDateTimeObject*)dt)->abstime))) + { + Py_DECREF(dt); + return NULL; + } + + Py_DECREF(dt); + res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_TIME); + Py_DECREF(mx); + return res; +} + +PyObject * +psyco_TimestampFromTicks(PyObject *self, PyObject *args) +{ + PyObject *mx, *res; + double ticks; + + if (!PyArg_ParseTuple(args, "d", &ticks)) + return NULL; + + if (!(mx = mxDateTimeP->DateTime_FromTicks(ticks))) + return NULL; + + res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_TIMESTAMP); + Py_DECREF(mx); + return res; +} + +#endif + +PyObject * +psyco_DateFromMx(PyObject *self, PyObject *args) +{ + PyObject *mx; + + if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx)) + return NULL; + + return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_DATE); +} + +PyObject * +psyco_TimeFromMx(PyObject *self, PyObject *args) +{ + PyObject *mx; + + if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTimeDelta_Type, &mx)) + return NULL; + + return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_TIME); +} + +PyObject * +psyco_TimestampFromMx(PyObject *self, PyObject *args) +{ + PyObject *mx; + + if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx)) + return NULL; + + return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_TIMESTAMP); +} + +PyObject * +psyco_IntervalFromMx(PyObject *self, PyObject *args) +{ + PyObject *mx; + + if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx)) + return NULL; + + return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, + PSYCO_MXDATETIME_INTERVAL); +}