Exemplo n.º 1
0
int
PQregisterResult(PGconn *conn, int which, PGregisterType *types,
	int count, PGresult *res)
{
	int i;
	PGtypeData *connData;
	char typname[PQT_MAXIDLEN + 1];
	char typschema[PQT_MAXIDLEN + 1];
	/* inherit typput and typget from record type */
	PGtypeHandler *h_rec = pqt_gethandler(NULL, 0, "pg_catalog", "record");

	PQseterror(NULL);

	if (!conn)
	{
		PQseterror("PGconn cannot be NULL");
		return FALSE;
	}

	if (!res)
	{
		PQseterror("PGresult cannot be NULL");
		return FALSE;
	}

	if (which == PQT_SUBCLASS)
	{
		PQseterror("Cannot call PQregisterResult for a subclass registration.");
		return FALSE;
	}

	if (!(connData = (PGtypeData *) PQinstanceData(conn, pqt_eventproc)))
	{
		PQseterror("PGconn is missing event data");
		return FALSE;
	}

	if (!types)
	{
		PQseterror("PGregisterType[] cannot be NULL");
		return FALSE;
	}

	if (count < 0)
	{
		PQseterror("PGregisterType[] count cannot be less than zero");
		return FALSE;
	}

	if(!checkTypeLookups(res, types, count))
		return FALSE;

	for (i=0; i < PQntuples(res); i++)
	{
		int flags;
		PGint2 typlen;
		PGtypeHandler *h;

		if (which == PQT_USERDEFINED && !types[i].typput && !types[i].typget)
		{
			PQseterror("Must provide a put and/or a get routine: '%s'",
				types[i].typname);
			return FALSE;
		}

		/* make sure conn's type handlers array is large enough */
		if (!expandHandlers(connData))
			return FALSE;

		/* create the handler */
		h = &connData->typhandlers[connData->typhcnt];
		memset(h, 0, sizeof(PGtypeHandler));

		if (!PQgetf(res, i, "%oid %oid %int2", 1, &h->typoid,
			2, &h->typoid_array, 3, &typlen))
		{
			return FALSE;
		}

		h->id = connData->typhcnt + countof(pg_handlers);
		h->typlen = (int) typlen;
		h->base_id = -1;

		if (which == PQT_USERDEFINED)
		{
			h->typput = types[i].typput;
			h->typget = types[i].typget;
		}
		else
		{
			h->typput = h_rec->typput;
			h->typget = h_rec->typget;
		}

		/* parse out type and schema names again */
		(void ) pqt_parsetype(types[i].typname, typschema, typname, &flags, 1);
		pqt_strcpy(h->typschema, sizeof(h->typschema), typschema);
		pqt_strcpy(h->typname, sizeof(h->typname), typname);

		/* Process composite attributes */
		if(which == PQT_COMPOSITE)
		{
			PGtext attrs;
			int nattrs;
			PGrecordAttDesc *attDescs;

			if (!PQgetf(res, i, "%text", 4, &attrs))
			{
				return FALSE;
			}

			if (!(attDescs = initAttDescs(h, attrs)))
				return FALSE;

			for (nattrs=0; *attrs; nattrs++)
			{
				char *p;
				char *name;
				int len;

				/* Attribute Text Encoding:
				 *   "attoid,attlen,atttypmod,name_hex attoid,etc..."
				 */

				attDescs[nattrs].attoid    = (int) strtol(attrs, &attrs, 10);
				attDescs[nattrs].attlen    = (int) strtol(attrs + 1, &attrs, 10);
				attDescs[nattrs].atttypmod = (int) strtol(attrs + 1, &attrs, 10);

				/* skip comma before name */
				attrs++;

				/* attribute name in hex */
				if (!(p = strchr(attrs, ' ')))
					p = attrs + strlen(attrs); /* last attr, point at NUL */

				/* truncate name if it exceeds buffer */
				len = (int) (p - attrs);
				if (len >= (int) sizeof(attDescs[nattrs].attname))
					len = (int) (sizeof(attDescs[nattrs].attname) - 1);

				/* hex decode and copy */
				for (name = attDescs[nattrs].attname; attrs < p; attrs += 2)
					*name++ = (char) (pqt_hex_to_dec(attrs[0]) << 4)
						| pqt_hex_to_dec(attrs[1]);
				*name = 0;
			}

			h->nattrs = nattrs;
			h->attDescs = attDescs;
		}

		connData->typhcnt++;
	}

	return TRUE;
}
Exemplo n.º 2
0
static int registerSubClass(PGtypeData *connData, const char *type_name,
	PGtypeProc typput, PGtypeProc typget)
{
	char *s;
	PGtypeHandler *h_sub;
	PGtypeHandler *h_base;
	char sub_typschema[PQT_MAXIDLEN + 1];
	char sub_typname[PQT_MAXIDLEN + 1];
	char base_typschema[PQT_MAXIDLEN + 1];
	char base_typname[PQT_MAXIDLEN + 1];
	char sub_fqtn[200];
	char base_fqtn[200];

	if (!(s = parseType(type_name, sub_typschema, sub_typname, 1)))
		return FALSE;

	if (*s != '=')
	{
		PQseterror("Missing inheritence operator '=': %s", type_name);
		return FALSE;
	}

	if (!parseType(s + 1, base_typschema, base_typname, 1))
		return FALSE;

	/* lookup the base handler */
	h_base = pqt_gethandler(connData->typhandlers, connData->typhcnt,
		base_typschema, base_typname);

	if (!h_base)
	{
		PQseterror("typname '%s' does not exist, '%s' cannot sub-class it",
			pqt_fqtn(base_fqtn, sizeof(base_fqtn), base_typschema, base_typname),
			pqt_fqtn(sub_fqtn, sizeof(sub_fqtn), sub_typschema, sub_typname));
		return FALSE;
	}

	/* cannot sub-class a record type */
	if (h_base->typoid == RECORDOID)
	{
		PQseterror("Cannot sub-class pg_catalog.record '%s'",
			pqt_fqtn(sub_fqtn, sizeof(sub_fqtn), sub_typschema, sub_typname));
		return FALSE;
	}

	if (!expandHandlers(connData))
		return FALSE;

	h_sub = &connData->typhandlers[connData->typhcnt];
	memset(h_sub, 0, sizeof(PGtypeHandler));

	h_sub->id = connData->typhcnt + countof(pg_handlers);
	h_sub->typlen = h_base->typlen;
	h_sub->typoid = h_base->typoid;
	h_sub->typoid_array = h_base->typoid_array;
	h_sub->typput = typput;
	h_sub->typget = typget;
	h_sub->base_id = h_base->id;

	pqt_strcpy(h_sub->typschema,
		sizeof(h_sub->typschema), sub_typschema);

	pqt_strcpy(h_sub->typname,
		sizeof(h_sub->typname), sub_typname);

	connData->typhcnt++;
	return TRUE;
}
Exemplo n.º 3
0
Arquivo: spec.c Projeto: beanhome/dev
char *pqt_parse(const char *format, PGtypeHandler *h, int hcnt,
                char *stmtBuf, size_t stmtBufLen, PGtypeHandler **out, size_t *stmtPos,
                int *typpos, int *flags)
{
    int specMark;
    char *s = skipQuotes((char *) format);
    char typname[PQT_MAXIDLEN + 1];
    char schema[PQT_MAXIDLEN + 1];
    char tmp[200];

    *out = NULL;

    if (!s)
        return NULL;

    /* found quotes to skip */
    if (s != format)
    {
        if (stmtBuf)
        {
            size_t n = s - format;
            CHKSTMTBUF(n);
            memcpy(stmtBuf + *stmtPos, format, n);
            (*stmtPos) += n;
        }

        return s;
    }

    specMark = *format;
    if (specMark != '%' && specMark != '#')
    {
        if (stmtBuf)
        {
            CHKSTMTBUF(1);
            stmtBuf[*stmtPos] = *format;
            (*stmtPos)++;
        }

        format++;
        return (char *) format;
    }

    /* spec skips % or # */
    if (!(s = pqt_parsetype(format + 1, schema, typname, flags, *typpos + 1)))
        return NULL;

    if (*flags & TYPFLAG_INVALID)
    {
        if (stmtBuf)
        {
            CHKSTMTBUF(1);
            stmtBuf[*stmtPos] = *format++;
            (*stmtPos)++;
            PQseterror(NULL); /* set by pqt_parsetype */
            return (char *) format;
        }

        return NULL;
    }

    (*typpos)++;

    if (!(*out = pqt_gethandler(h, hcnt, schema, typname)))
    {
        PQseterror("Uknown type '%s' (position %d)",
                   pqt_fqtn(tmp, sizeof(tmp), schema, typname), *typpos);
        return NULL;
    }

    if (stmtBuf)
    {
        int n = pqt_snprintf(tmp, sizeof(tmp), "$%d", *typpos);
        CHKSTMTBUF(n);
        memcpy(stmtBuf + *stmtPos, tmp, n);
        (*stmtPos) += n;
    }

    if (!(*out)->typput)
    {
        PGtypeHandler *o = pqt_gethandlerbyid(h, hcnt, h->base_id);
        if (!o || !o->typput)
        {
            PQseterror(
                "Type '%s' doesn't support put operations (position %d)",
                pqt_fqtn(tmp, sizeof(tmp), (*out)->typschema, (*out)->typname), *typpos);

            *out = NULL;
            return NULL;
        }

        *out = o;
    }

    if ((*flags & TYPFLAG_POINTER) && !pqt_allowsptr(*out))
    {
        PQseterror(
            "Type '%s' doesn't support putting pointers (position %d)",
            pqt_fqtn(tmp, sizeof(tmp), (*out)->typschema, (*out)->typname), *typpos);

        *out = NULL;
        return NULL;
    }

    if (specMark == '#')
        (*flags) |= TYPFLAG_BYNAME;

    return s;
}