/* * Convert to a domain type. */ static Datum PLyObject_ToDomain(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray) { Datum result; PLyObToDatum *base = arg->u.domain.base; result = base->func(base, plrv, isnull, inarray); domain_check(result, *isnull, arg->typoid, &arg->u.domain.domain_info, arg->mcxt); return result; }
static VALUE math_sqrt(VALUE obj, VALUE x) { double d0, d; Need_Float(x); errno = 0; d0 = RFLOAT_VALUE(x); d = sqrt(d0); domain_check(d0, d, "sqrt"); return DBL2NUM(d); }
/* * Convert a Python object to a PostgreSQL bool datum. This can't go * through the generic conversion function, because Python attaches a * Boolean value to everything, more things than the PostgreSQL bool * type can parse. */ static Datum PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv) { Datum rv; Assert(plrv != Py_None); rv = BoolGetDatum(PyObject_IsTrue(plrv)); if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN) domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt); return rv; }
static VALUE math_log10(VALUE obj, VALUE x) { double d0, d; Need_Float(x); errno = 0; d0 = RFLOAT_VALUE(x); d = log10(d0); domain_check(d0, d, "log10"); infinity_check(x, d, "log10"); return DBL2NUM(d); }
static VALUE math_lgamma(VALUE obj, VALUE x) { double d0, d; int sign; VALUE v; Need_Float(x); errno = 0; d0 = RFLOAT_VALUE(x); d = lgamma_r(d0, &sign); domain_check(d0, d, "lgamma"); v = DBL2NUM(d); return rb_assoc_new(v, INT2FIX(sign)); }
static Datum PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv) { ArrayType *array; Datum rv; int i; Datum *elems; bool *nulls; int len; int lbs; Assert(plrv != Py_None); if (!PySequence_Check(plrv)) PLy_elog(ERROR, "return value of function with array return type is not a Python sequence"); len = PySequence_Length(plrv); elems = palloc(sizeof(*elems) * len); nulls = palloc(sizeof(*nulls) * len); for (i = 0; i < len; i++) { PyObject *obj = PySequence_GetItem(plrv, i); if (obj == Py_None) nulls[i] = true; else { nulls[i] = false; elems[i] = arg->elm->func(arg->elm, -1, obj); } Py_XDECREF(obj); } lbs = 1; array = construct_md_array(elems, nulls, 1, &len, &lbs, get_base_element_type(arg->typoid), arg->elm->typlen, arg->elm->typbyval, arg->elm->typalign); /* * If the result type is a domain of array, the resulting array must be * checked. */ rv = PointerGetDatum(array); if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN) domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt); return rv; }
static VALUE math_gamma(VALUE obj, VALUE x) { static const double fact_table[] = { /* fact(0) */ 1.0, /* fact(1) */ 1.0, /* fact(2) */ 2.0, /* fact(3) */ 6.0, /* fact(4) */ 24.0, /* fact(5) */ 120.0, /* fact(6) */ 720.0, /* fact(7) */ 5040.0, /* fact(8) */ 40320.0, /* fact(9) */ 362880.0, /* fact(10) */ 3628800.0, /* fact(11) */ 39916800.0, /* fact(12) */ 479001600.0, /* fact(13) */ 6227020800.0, /* fact(14) */ 87178291200.0, /* fact(15) */ 1307674368000.0, /* fact(16) */ 20922789888000.0, /* fact(17) */ 355687428096000.0, /* fact(18) */ 6402373705728000.0, /* fact(19) */ 121645100408832000.0, /* fact(20) */ 2432902008176640000.0, /* fact(21) */ 51090942171709440000.0, /* fact(22) */ 1124000727777607680000.0, /* fact(23)=25852016738884976640000 needs 56bit mantissa which is * impossible to represent exactly in IEEE 754 double which have * 53bit mantissa. */ }; double d0, d; double intpart, fracpart; int n; Need_Float(x); d0 = RFLOAT_VALUE(x); fracpart = modf(d0, &intpart); if (fracpart == 0.0 && 0 < intpart && (n = (int)intpart - 1) < numberof(fact_table)) { return DBL2NUM(fact_table[n]); } errno = 0; d = tgamma(d0); domain_check(d0, d, "gamma"); return DBL2NUM(d); }
static VALUE math_log(int argc, VALUE *argv) { VALUE x, base; double d0, d; rb_scan_args(argc, argv, "11", &x, &base); Need_Float(x); errno = 0; d0 = RFLOAT_VALUE(x); d = log(d0); if (argc == 2) { Need_Float(base); d /= log(RFLOAT_VALUE(base)); } domain_check(d0, d, "log"); infinity_check(x, d, "log"); return DBL2NUM(d); }
/* * Convert a Python object to a PostgreSQL bytea datum. This doesn't * go through the generic conversion function to circumvent problems * with embedded nulls. And it's faster this way. */ static Datum PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv) { PyObject *volatile plrv_so = NULL; Datum rv; Assert(plrv != Py_None); plrv_so = PyObject_Bytes(plrv); if (!plrv_so) PLy_elog(ERROR, "could not create bytes representation of Python object"); PG_TRY(); { char *plrv_sc = PyBytes_AsString(plrv_so); size_t len = PyBytes_Size(plrv_so); size_t size = len + VARHDRSZ; bytea *result = palloc(size); SET_VARSIZE(result, size); memcpy(VARDATA(result), plrv_sc, len); rv = PointerGetDatum(result); } PG_CATCH(); { Py_XDECREF(plrv_so); PG_RE_THROW(); } PG_END_TRY(); Py_XDECREF(plrv_so); if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN) domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt); return rv; }
func_decl * datatype_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (num_parameters < 2 || !parameters[0].is_ast() || !is_sort(parameters[0].get_ast())) { m_manager->raise_exception("invalid parameters for datatype operator"); return 0; } sort * datatype = to_sort(parameters[0].get_ast()); if (datatype->get_family_id() != m_family_id || datatype->get_decl_kind() != DATATYPE_SORT) { m_manager->raise_exception("invalid parameters for datatype operator"); return 0; } for (unsigned i = 1; i < num_parameters; i++) { if (!parameters[i].is_int()) { m_manager->raise_exception("invalid parameters for datatype operator"); return 0; } } unsigned c_idx = parameters[1].get_int(); unsigned tid = datatype->get_parameter(1).get_int(); unsigned o = datatype->get_parameter(2 + 2 * tid + 1).get_int(); unsigned num_constructors = datatype->get_parameter(o).get_int(); if (c_idx >= num_constructors) { m_manager->raise_exception("invalid parameters for datatype operator"); return 0; } unsigned k_i = datatype->get_parameter(o + 1 + c_idx).get_int(); switch (k) { case OP_DT_CONSTRUCTOR: if (num_parameters != 2) { m_manager->raise_exception("invalid parameters for datatype constructor"); return 0; } else { symbol c_name = datatype->get_parameter(k_i).get_symbol(); unsigned num_accessors = datatype->get_parameter(k_i + 2).get_int(); if (num_accessors != arity) { m_manager->raise_exception("invalid domain size for datatype constructor"); return 0; } // // the reference count to domain could be 0. // we need to ensure that creating a temporary // copy of the same type causes a free. // sort_ref_vector domain_check(*m_manager); for (unsigned r = 0; r < num_accessors; r++) { sort_ref ty(*m_manager); ty = get_type(*m_manager, m_family_id, datatype, datatype->get_parameter(k_i + 4 + 2*r)); domain_check.push_back(ty); if (ty != domain[r]) { m_manager->raise_exception("invalid domain for datatype constructor"); return 0; } } func_decl_info info(m_family_id, k, num_parameters, parameters); info.m_private_parameters = true; SASSERT(info.private_parameters()); return m_manager->mk_func_decl(c_name, arity, domain, datatype, info); } case OP_DT_RECOGNISER: if (num_parameters != 2 || arity != 1 || domain[0] != datatype) { m_manager->raise_exception("invalid parameters for datatype recogniser"); return 0; } else { symbol r_name = datatype->get_parameter(k_i + 1).get_symbol(); sort * b = m_manager->mk_bool_sort(); func_decl_info info(m_family_id, k, num_parameters, parameters); info.m_private_parameters = true; SASSERT(info.private_parameters()); return m_manager->mk_func_decl(r_name, arity, domain, b, info); } case OP_DT_ACCESSOR: if (num_parameters != 3 || arity != 1 || domain[0] != datatype) { m_manager->raise_exception("invalid parameters for datatype accessor"); return 0; } else { unsigned a_idx = parameters[2].get_int(); unsigned num_accessors = datatype->get_parameter(k_i + 2).get_int(); if (a_idx >= num_accessors) { m_manager->raise_exception("invalid datatype accessor"); return 0; } symbol a_name = datatype->get_parameter(k_i + 3 + 2*a_idx).get_symbol(); sort * a_type = get_type(*m_manager, m_family_id, datatype, datatype->get_parameter(k_i + 4 + 2*a_idx)); func_decl_info info(m_family_id, k, num_parameters, parameters); info.m_private_parameters = true; SASSERT(info.private_parameters()); return m_manager->mk_func_decl(a_name, arity, domain, a_type, info); } break; default: m_manager->raise_exception("invalid datatype operator kind"); return 0; } }