Beispiel #1
0
/**
 * @fn      Datum reorg_indexdef(PG_FUNCTION_ARGS)
 * @brief   Reproduce DDL that create index at the temp table.
 *
 * reorg_indexdef(index, table)
 *
 * @param	index	Oid of target index.
 * @param	table	Oid of table of the index.
 * @retval			Create index DDL for temp table.
 */
Datum
reorg_indexdef(PG_FUNCTION_ARGS)
{
    Oid				index = PG_GETARG_OID(0);
    Oid				table = PG_GETARG_OID(1);
    IndexDef		stmt;
    StringInfoData	str;

    parse_indexdef(&stmt, index, table);
    initStringInfo(&str);
    appendStringInfo(&str, "%s index_%u ON reorg.table_%u USING %s (%s)%s",
                     stmt.create, index, table, stmt.type, stmt.columns, stmt.options);

    PG_RETURN_TEXT_P(cstring_to_text(str.data));
}
Beispiel #2
0
/**
 * @fn      Datum repack_indexdef(PG_FUNCTION_ARGS)
 * @brief   Reproduce DDL that create index at the temp table.
 *
 * repack_indexdef(index, table)
 *
 * @param	index		Oid of target index.
 * @param	table		Oid of table of the index.
 * @param	tablespace	Namespace for the index. If NULL keep the original.
 * @param   boolean		Whether to use CONCURRENTLY when creating the index.
 * @retval			Create index DDL for temp table.
 */
Datum
repack_indexdef(PG_FUNCTION_ARGS)
{
	Oid				index;
	Oid				table;
	Name			tablespace = NULL;
	IndexDef		stmt;
	StringInfoData	str;
	bool			concurrent_index = PG_GETARG_BOOL(3);

	if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
		PG_RETURN_NULL();

	index = PG_GETARG_OID(0);
	table = PG_GETARG_OID(1);

	if (!PG_ARGISNULL(2))
		tablespace = PG_GETARG_NAME(2);

	parse_indexdef(&stmt, index, table);

	initStringInfo(&str);
	if (concurrent_index)
		appendStringInfo(&str, "%s CONCURRENTLY index_%u ON %s USING %s (%s)%s",
			stmt.create, index, stmt.table, stmt.type, stmt.columns, stmt.options);
	else
		appendStringInfo(&str, "%s index_%u ON repack.table_%u USING %s (%s)%s",
			stmt.create, index, table, stmt.type, stmt.columns, stmt.options);

	/* specify the new tablespace or the original one if any */
	if (tablespace || stmt.tablespace)
		appendStringInfo(&str, " TABLESPACE %s",
			(tablespace ? NameStr(*tablespace) : stmt.tablespace));

	if (stmt.where)
		appendStringInfo(&str, " WHERE %s", stmt.where);

	PG_RETURN_TEXT_P(cstring_to_text(str.data));
}
Beispiel #3
0
/**
 * @fn      Datum reorg_get_index_keys(PG_FUNCTION_ARGS)
 * @brief   Get key definition of the index.
 *
 * reorg_get_index_keys(index, table)
 *
 * @param	index	Oid of target index.
 * @param	table	Oid of table of the index.
 * @retval			Create index DDL for temp table.
 *
 * FIXME: this function is named get_index_keys, but actually returns
 * an expression for ORDER BY clause. get_order_by() might be a better name.
 */
Datum
reorg_get_index_keys(PG_FUNCTION_ARGS)
{
    Oid				index = PG_GETARG_OID(0);
    Oid				table = PG_GETARG_OID(1);
    IndexDef		stmt;
    char		   *token;
    char		   *next;
    StringInfoData	str;
    Relation		indexRel = NULL;
    int				nattr;

    parse_indexdef(&stmt, index, table);
    elog(DEBUG2, "indexdef.create  = %s", stmt.create);
    elog(DEBUG2, "indexdef.index   = %s", stmt.index);
    elog(DEBUG2, "indexdef.table   = %s", stmt.table);
    elog(DEBUG2, "indexdef.type    = %s", stmt.type);
    elog(DEBUG2, "indexdef.columns = %s", stmt.columns);
    elog(DEBUG2, "indexdef.options = %s", stmt.options);

    /*
     * FIXME: this is very unreliable implementation but I don't want to
     * re-implement customized versions of pg_get_indexdef_string...
     *
     * TODO: Support ASC/DESC and NULL FIRST/LAST.
     */

    initStringInfo(&str);
    for (nattr = 0, next = stmt.columns; next; nattr++)
    {
        char *opcname;

        token = next;
        while (isspace((unsigned char) *token))
            token++;
        next = skip_until(index, next, ',');
        opcname = skip_until(index, token, ' ');
        if (opcname)
        {
            /* lookup default operator name from operator class */

            Oid				opclass;
            Oid				oprid;
            int16			strategy = BTLessStrategyNumber;
            Oid				opcintype;
            Oid				opfamily;
            HeapTuple		tp;
            Form_pg_opclass	opclassTup;

            opclass = OpclassnameGetOpcid(BTREE_AM_OID, opcname);

            /* Retrieve operator information. */
            tp = SearchSysCache(CLAOID, ObjectIdGetDatum(opclass), 0, 0, 0);
            if (!HeapTupleIsValid(tp))
                elog(ERROR, "cache lookup failed for opclass %u", opclass);
            opclassTup = (Form_pg_opclass) GETSTRUCT(tp);
            opfamily = opclassTup->opcfamily;
            opcintype = opclassTup->opcintype;
            ReleaseSysCache(tp);

            if (!OidIsValid(opcintype))
            {
                if (indexRel == NULL)
                    indexRel = index_open(index, NoLock);

                opcintype = RelationGetDescr(indexRel)->attrs[nattr]->atttypid;
            }

            oprid = get_opfamily_member(opfamily, opcintype, opcintype, strategy);
            if (!OidIsValid(oprid))
                elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
                     strategy, opcintype, opcintype, opfamily);


            opcname[-1] = '\0';
            appendStringInfo(&str, "%s USING %s", token, get_opname(oprid));
        }
        else
            appendStringInfoString(&str, token);
        if (next)
            appendStringInfoString(&str, ", ");
    }

    if (indexRel != NULL)
        index_close(indexRel, NoLock);

    PG_RETURN_TEXT_P(cstring_to_text(str.data));
}