Files
documentdb/pg_helio_api/include/utils/query_utils.h
T
Vinod Sridharan ac2b3d7837 Merged PR 1353542: [Pgmongo|Index] Use sequential index builds for unsharded tables
### Does this PR have any customer impact?
Yes

### Type (Feature, Refactoring, Bugfix, DevOps, Testing, Perf, etc)
Perf/Bugfix

### Does it involve schema level changes? (Table, Column, Index, UDF, etc level changes)
No

### Are you introducing any new config? If yes, do you have tests with and without them being set?
No
### Release Note (Refer [Template](../docs/release_notes/pgmongo_template.md))

### Description
For unsharded collections we create 32 connections per table for create indexes and only 1 of them does any work: Use sequential access to better utilize connections.
2024-05-24 10:41:23 +03:00

141 lines
5.7 KiB
C

/*-------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* include/utils/query_utils.h
*
* Utilities to execute a command/query.
*
*-------------------------------------------------------------------------
*/
#include <postgres.h>
#include <utils/array.h>
#include <executor/spi.h>
#ifndef QUERY_UTILS_H
#define QUERY_UTILS_H
/*
* Execute a query within the current transaction and return the first datum
* of the first tuple returned by given query (if any).
*
* Rollbacking or aborting the current transaction / subtransaction is
* guaranteed to rollback the query that has been executed even if query
* execution has been completed already.
*/
Datum ExtensionExecuteQueryViaSPI(const char *query, bool readOnly, int expectedSPIOK,
bool *isNull);
void ExtensionExecuteMultiValueQueryViaSPI(const char *query, bool readOnly,
int expectedSPIOK, Datum *datums,
bool *isNull, int numValues);
Datum ExtensionExecuteQueryWithArgsViaSPI(const char *query, int nargs, Oid *argTypes,
Datum *argValues, char *argNulls,
bool readOnly, int expectedSPIOK,
bool *isNull);
Datum ExtensionExecuteCappedQueryWithArgsViaSPI(const char *query, int nargs,
Oid *argTypes,
Datum *argValues, char *argNulls,
bool readOnly, int expectedSPIOK,
bool *isNull, int statementTimeout,
int lockTimeout);
void ExtensionExecuteMultiValueQueryWithArgsViaSPI(const char *query, int nargs,
Oid *argTypes, Datum *argValues,
char *argNulls, bool readOnly,
int expectedSPIOK, Datum *datums,
bool *isNull, int numValues);
uint64 ExtensionExecuteCappedStatementWithArgsViaSPI(const char *query, int nargs,
Oid *argTypes,
Datum *argValues, char *argNulls,
bool readOnly, int expectedSPIOK,
int statementTimeout, int
lockTimeout);
/*
* Execute a query outside the current transaction and return the first
* attribute of the first tuple returned by given query (if any).
*
* After the execution of given query completes, it cannot be rollbacked even
* if current transaction / subtransaction rollbacks or aborts.
*
* Otherwise, i.e.: if this function didn't return yet, then there is still
* a chance to cancel the query when rollbacking or aborting the current the
* transaction / subtransaction since the abort handlers in
* TransactionCallback & SubTransactionCallback will then try
* cancelling the query. However, it is still not guaranteed that given query
* will be rollbacked. This is because;
* i) The transaction that we started over the libpq connection might got
* committed already, i.e.: remote transaction is not active anymore.
* ii) Theoretically, connection establishment to localhost might still fail
* while trying to send the cancellation.
*
* [1] Why can using a libpq connection might cause an undetectable deadlock ?
* (Please keep in mind that "s" means "session" and "r" means "resource"
* in this scenario.)
*
* Suppose that s1 acquired r1 and waits for r2, and s2 acquired r2 and
* waits for r1. In that case, postgres would throw an error telling that
* those two sessions entered into a deadlock. Or, if those resources belong
* to different Citus nodes (coordinator / MX worker), then Citus would
* report this as a "distributed deadlock" instead of postgres.
*
* And now let's consider another scenario. Suppose that s1 acquired r1
* and the libpq connection (initiated via ExtensionExecuteQueryOnLocalhostViaLibPQ())
* that s1 is waiting for is waiting for r2, and s2 acquired r2 and it
* waits for r1. Here, s2 waits for s1 to release a resource, and s1 waits
* for the libpq to finish its IO; and that libpq connection is waiting for
* s2 to release a resource. Given the wait-triangle here, one could expect
* postgres or Citus to detect this as a deadlock condition where three
* processes involved; but this is not the case. This is because, postgres
* doesn't take the connection-IO waits into the account (even if they are
* local) when detecting deadlock conditions and such a scenario would cause
* those processes to wait for each other indefinitely. For this reason, callers
* should be careful about such cases when using ExtensionExecuteQueryViaLibPQ()
* instead of ExtensionExecuteQueryViaSPI() or such.
*/
char * ExtensionExecuteQueryOnLocalhostViaLibPQ(char *query);
/*
* Same as ExtensionExecuteQueryOnLocalhostViaLibPQ, but connects as specific user.
*/
char * ExtensionExecuteQueryAsUserOnLocalhostViaLibPQ(char *query, const Oid userOid,
bool useSerialExecution);
/* Same as ExtensionExecuteQueryAsUserOnLocalhostViaLibPQ, but it allows to execute parameterized query */
char * ExtensionExecuteQueryWithArgsAsUserOnLocalhostViaLibPQ(char *query, const Oid
userOid, int nParams,
Oid *paramTypes, const
char **parameterValues);
/*
* Helper method to create a string query using a variable number
* of arguments - similar to doing
* StringInfo s = makeStringInfo();
* appendStringInfo(s, "queryFormat", args);
* return s->data;
*/
pg_attribute_printf(1, 2) inline static const char *
FormatSqlQuery(const char *queryFormat, ...)
{
StringInfoData cmdbuf;
initStringInfo(&cmdbuf);
for (;;)
{
va_list args;
int needed;
va_start(args, queryFormat);
needed = appendStringInfoVA(&cmdbuf, queryFormat, args);
va_end(args);
if (needed == 0)
{
break; /* success */
}
enlargeStringInfo(&cmdbuf, needed);
}
return cmdbuf.data;
}
#endif