First working version for debug text output at least
parent
0241c144fc
commit
6a212e9e4c
|
@ -0,0 +1,47 @@
|
||||||
|
---
|
||||||
|
# BasedOnStyle: Mozilla
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
AlignEscapedNewlinesLeft: false
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakTemplateDeclarations: false
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
BreakBeforeBinaryOperators: false
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BinPackParameters: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
DerivePointerBinding: true
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
IndentCaseLabels: true
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCSpaceBeforeProtocolList: false
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 60
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerBindsToType: true
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
Standard: Cpp03
|
||||||
|
IndentWidth: 2
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
IndentFunctionDeclarationAfterType: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpaceAfterControlStatementKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
...
|
||||||
|
|
|
@ -22,11 +22,10 @@ message DatumMessage {
|
||||||
optional bytes datum_bytes = 9;
|
optional bytes datum_bytes = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
message TxnMessage {
|
message RowMessage {
|
||||||
optional sint64 timestamp = 1;
|
optional sint64 commit_time = 1;
|
||||||
optional int64 xid = 2;
|
optional string table = 2;
|
||||||
optional string table = 3;
|
optional Op op = 3;
|
||||||
optional Op op = 4;
|
repeated DatumMessage new_tuple = 4;
|
||||||
optional DatumMessage new_datum = 5;
|
repeated DatumMessage old_tuple = 5;
|
||||||
optional DatumMessage old_datum = 6;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
#include "funcapi.h"
|
#include "funcapi.h"
|
||||||
#include "catalog/pg_class.h"
|
#include "catalog/pg_class.h"
|
||||||
|
@ -43,9 +46,19 @@
|
||||||
|
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
|
|
||||||
|
/* define a time macro to convert TimestampTz into something more sane,
|
||||||
|
* which in this case is microseconds since epoch
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
#define TIMESTAMPTZ_TO_USEC_SINCE_EPOCH(t) \
|
||||||
|
t + ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY * USECS_PER_SEC);
|
||||||
|
#else
|
||||||
|
#define TIMESTAMPTZ_TO_USEC_SINCE_EPOCH(t) \
|
||||||
|
(t + ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY)) * 1000.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MemoryContext context;
|
MemoryContext context;
|
||||||
Decoderbufs__TxnMessage *txn_msg;
|
|
||||||
bool debug_mode;
|
bool debug_mode;
|
||||||
} DecoderData;
|
} DecoderData;
|
||||||
|
|
||||||
|
@ -82,12 +95,11 @@ static void pg_decode_startup(LogicalDecodingContext *ctx,
|
||||||
DecoderData *data;
|
DecoderData *data;
|
||||||
|
|
||||||
data = palloc(sizeof(DecoderData));
|
data = palloc(sizeof(DecoderData));
|
||||||
data->context = AllocSetContextCreate(ctx->context, "decoderbufs context",
|
data->context = AllocSetContextCreate(
|
||||||
ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE,
|
ctx->context, "decoderbufs context", ALLOCSET_DEFAULT_MINSIZE,
|
||||||
ALLOCSET_DEFAULT_MAXSIZE);
|
ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE);
|
||||||
|
|
||||||
ctx->output_plugin_private = data;
|
ctx->output_plugin_private = data;
|
||||||
|
|
||||||
opt->output_type = OUTPUT_PLUGIN_BINARY_OUTPUT;
|
opt->output_type = OUTPUT_PLUGIN_BINARY_OUTPUT;
|
||||||
|
|
||||||
foreach(option, ctx->output_plugin_options) {
|
foreach(option, ctx->output_plugin_options) {
|
||||||
|
@ -95,17 +107,16 @@ static void pg_decode_startup(LogicalDecodingContext *ctx,
|
||||||
Assert(elem->arg == NULL || IsA(elem->arg, String));
|
Assert(elem->arg == NULL || IsA(elem->arg, String));
|
||||||
|
|
||||||
if (strcmp(elem->defname, "debug-mode") == 0) {
|
if (strcmp(elem->defname, "debug-mode") == 0) {
|
||||||
bool debug_mode;
|
|
||||||
if (elem->arg == NULL)
|
if (elem->arg == NULL)
|
||||||
debug_mode = false;
|
data->debug_mode = false;
|
||||||
else if (!parse_bool(strVal(elem->arg), &debug_mode))
|
else if (!parse_bool(strVal(elem->arg), &data->debug_mode))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("could not parse value \"%s\" for parameter \"%s\"",
|
errmsg("could not parse value \"%s\" for parameter \"%s\"",
|
||||||
strVal(elem->arg), elem->defname)));
|
strVal(elem->arg), elem->defname)));
|
||||||
|
|
||||||
if (debug_mode)
|
if (data->debug_mode)
|
||||||
opt->output_type = OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
|
opt->output_type = OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
|
||||||
} else {
|
} else {
|
||||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("option \"%s\" = \"%s\" is unknown", elem->defname,
|
errmsg("option \"%s\" = \"%s\" is unknown", elem->defname,
|
||||||
|
@ -114,25 +125,6 @@ static void pg_decode_startup(LogicalDecodingContext *ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_txn_msg_datums(Decoderbufs__TxnMessage *msg) {
|
|
||||||
if (msg->new_datum) {
|
|
||||||
if (msg->new_datum->has_datum_bytes) {
|
|
||||||
pfree(msg->new_datum->datum_bytes.data);
|
|
||||||
msg->new_datum->datum_bytes.data = NULL;
|
|
||||||
msg->new_datum->datum_bytes.len = 0;
|
|
||||||
}
|
|
||||||
pfree(msg->new_datum);
|
|
||||||
}
|
|
||||||
if (msg->old_datum) {
|
|
||||||
if (msg->old_datum->has_datum_bytes) {
|
|
||||||
pfree(msg->old_datum->datum_bytes.data);
|
|
||||||
msg->old_datum->datum_bytes.data = NULL;
|
|
||||||
msg->old_datum->datum_bytes.len = 0;
|
|
||||||
}
|
|
||||||
pfree(msg->old_datum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cleanup this plugin's resources */
|
/* cleanup this plugin's resources */
|
||||||
static void pg_decode_shutdown(LogicalDecodingContext *ctx) {
|
static void pg_decode_shutdown(LogicalDecodingContext *ctx) {
|
||||||
DecoderData *data = ctx->output_plugin_private;
|
DecoderData *data = ctx->output_plugin_private;
|
||||||
|
@ -144,154 +136,228 @@ static void pg_decode_shutdown(LogicalDecodingContext *ctx) {
|
||||||
/* BEGIN callback */
|
/* BEGIN callback */
|
||||||
static void pg_decode_begin_txn(LogicalDecodingContext *ctx,
|
static void pg_decode_begin_txn(LogicalDecodingContext *ctx,
|
||||||
ReorderBufferTXN *txn) {
|
ReorderBufferTXN *txn) {
|
||||||
DecoderData *data = ctx->output_plugin_private;
|
|
||||||
Decoderbufs__TxnMessage msg = DECODERBUFS__TXN_MESSAGE__INIT;
|
|
||||||
data->txn_msg = &msg;
|
|
||||||
data->txn_msg->xid = txn->xid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* COMMIT callback */
|
/* COMMIT callback */
|
||||||
static void pg_decode_commit_txn(LogicalDecodingContext *ctx,
|
static void pg_decode_commit_txn(LogicalDecodingContext *ctx,
|
||||||
ReorderBufferTXN *txn, XLogRecPtr commit_lsn) {
|
ReorderBufferTXN *txn, XLogRecPtr commit_lsn) {
|
||||||
DecoderData *data = ctx->output_plugin_private;
|
}
|
||||||
Decoderbufs__TxnMessage *msg = data->txn_msg;
|
|
||||||
msg->timestamp = txn->commit_time;
|
|
||||||
|
|
||||||
OutputPluginPrepareWrite(ctx, true);
|
/* convenience method to free up sub-messages */
|
||||||
size_t psize = decoderbufs__txn_message__get_packed_size(msg);
|
static void free_row_msg_subs(Decoderbufs__RowMessage *msg) {
|
||||||
void *packed = palloc(psize);
|
if (!msg) {
|
||||||
size_t ssize = decoderbufs__txn_message__pack(msg, packed);
|
return;
|
||||||
appendBinaryStringInfo(ctx->out, packed, ssize);
|
}
|
||||||
OutputPluginWrite(ctx, true);
|
|
||||||
|
|
||||||
pfree(packed);
|
pfree(msg->table);
|
||||||
free_txn_msg_datums(msg);
|
if (msg->n_new_tuple > 0) {
|
||||||
|
for (int i=0; i < msg->n_new_tuple; i++) {
|
||||||
|
if (msg->new_tuple[i]) {
|
||||||
|
if (msg->new_tuple[i]->datum_string) {
|
||||||
|
pfree(msg->new_tuple[i]->datum_string);
|
||||||
|
} else if (msg->new_tuple[i]->has_datum_bytes) {
|
||||||
|
pfree(msg->new_tuple[i]->datum_bytes.data);
|
||||||
|
msg->new_tuple[i]->datum_bytes.data = NULL;
|
||||||
|
msg->new_tuple[i]->datum_bytes.len = 0;
|
||||||
|
}
|
||||||
|
pfree(msg->new_tuple[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pfree(msg->new_tuple);
|
||||||
|
}
|
||||||
|
if (msg->n_old_tuple > 0) {
|
||||||
|
for (int i=0; i < msg->n_old_tuple; i++) {
|
||||||
|
if (msg->old_tuple[i]) {
|
||||||
|
if (msg->old_tuple[i]->datum_string) {
|
||||||
|
pfree(msg->old_tuple[i]->datum_string);
|
||||||
|
} else if (msg->old_tuple[i]->has_datum_bytes) {
|
||||||
|
pfree(msg->old_tuple[i]->datum_bytes.data);
|
||||||
|
msg->old_tuple[i]->datum_bytes.data = NULL;
|
||||||
|
msg->old_tuple[i]->datum_bytes.len = 0;
|
||||||
|
}
|
||||||
|
pfree(msg->old_tuple[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pfree(msg->old_tuple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_tuple_msg(StringInfo out, Decoderbufs__DatumMessage **tup, size_t n) {
|
||||||
|
if (tup) {
|
||||||
|
for (int i=0; i < n; i++) {
|
||||||
|
Decoderbufs__DatumMessage *dmsg = tup[i];
|
||||||
|
if (dmsg->column_name)
|
||||||
|
appendStringInfo(out, "column_name[%s]", dmsg->column_name);
|
||||||
|
if (dmsg->has_column_type) {
|
||||||
|
appendStringInfo(out, ", column_type[%" PRId64 "]", dmsg->column_type);
|
||||||
|
switch (dmsg->column_type) {
|
||||||
|
case INT2OID:
|
||||||
|
case INT4OID:
|
||||||
|
appendStringInfo(out, ", datum[%d]", dmsg->datum_int32);
|
||||||
|
break;
|
||||||
|
case INT8OID:
|
||||||
|
appendStringInfo(out, ", datum[%" PRId64 "]", dmsg->datum_int64);
|
||||||
|
break;
|
||||||
|
case FLOAT4OID:
|
||||||
|
appendStringInfo(out, ", datum[%f]", dmsg->datum_float);
|
||||||
|
break;
|
||||||
|
case FLOAT8OID:
|
||||||
|
case NUMERICOID:
|
||||||
|
appendStringInfo(out, ", datum[%f]", dmsg->datum_double);
|
||||||
|
break;
|
||||||
|
case TEXTOID:
|
||||||
|
appendStringInfo(out, ", datum[%s]", dmsg->datum_string);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
appendStringInfo(out, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this doesn't seem to be available in the public api (unfortunate) */
|
/* this doesn't seem to be available in the public api (unfortunate) */
|
||||||
static double numeric_to_double_no_overflow(Numeric num) {
|
static double numeric_to_double_no_overflow(Numeric num) {
|
||||||
char *tmp;
|
char *tmp;
|
||||||
double val;
|
double val;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
|
tmp = DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(num)));
|
||||||
NumericGetDatum(num)));
|
|
||||||
|
|
||||||
/* unlike float8in, we ignore ERANGE from strtod */
|
/* unlike float8in, we ignore ERANGE from strtod */
|
||||||
val = strtod(tmp, &endptr);
|
val = strtod(tmp, &endptr);
|
||||||
if (*endptr != '\0')
|
if (*endptr != '\0') {
|
||||||
{
|
/* shouldn't happen ... */
|
||||||
/* shouldn't happen ... */
|
ereport(ERROR,
|
||||||
ereport(ERROR,
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
tmp)));
|
||||||
tmp)));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pfree(tmp);
|
pfree(tmp);
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_datum_value(Decoderbufs__DatumMessage *datum_msg, Oid typid, Oid typoutput, Datum datum) {
|
static void set_datum_value(Decoderbufs__DatumMessage *datum_msg, Oid typid,
|
||||||
Numeric num;
|
Oid typoutput, Datum datum) {
|
||||||
char c;
|
Numeric num;
|
||||||
bytea *valptr;
|
char c;
|
||||||
char *output;
|
bytea *valptr;
|
||||||
switch (typid) {
|
char *output;
|
||||||
case BOOLOID:
|
switch (typid) {
|
||||||
datum_msg->datum_bool = DatumGetBool(datum);
|
case BOOLOID:
|
||||||
break;
|
datum_msg->datum_bool = DatumGetBool(datum);
|
||||||
case INT2OID:
|
datum_msg->has_datum_bool = true;
|
||||||
datum_msg->datum_int32 = DatumGetInt16(datum);
|
break;
|
||||||
break;
|
case INT2OID:
|
||||||
case INT4OID:
|
datum_msg->datum_int32 = DatumGetInt16(datum);
|
||||||
datum_msg->datum_int32 = DatumGetInt32(datum);
|
datum_msg->has_datum_int32 = true;
|
||||||
break;
|
break;
|
||||||
case INT8OID:
|
case INT4OID:
|
||||||
datum_msg->datum_int64 = DatumGetInt64(datum);
|
datum_msg->datum_int32 = DatumGetInt32(datum);
|
||||||
break;
|
datum_msg->has_datum_int32 = true;
|
||||||
case OIDOID:
|
break;
|
||||||
break;
|
case INT8OID:
|
||||||
case FLOAT4OID:
|
case OIDOID:
|
||||||
datum_msg->datum_float = DatumGetFloat4(datum);
|
datum_msg->datum_int64 = DatumGetInt64(datum);
|
||||||
break;
|
datum_msg->has_datum_int64 = true;
|
||||||
case FLOAT8OID:
|
break;
|
||||||
datum_msg->datum_double = DatumGetFloat8(datum);
|
case FLOAT4OID:
|
||||||
break;
|
datum_msg->datum_float = DatumGetFloat4(datum);
|
||||||
case NUMERICOID:
|
datum_msg->has_datum_float = true;
|
||||||
num = DatumGetNumeric(datum);
|
break;
|
||||||
if (!numeric_is_nan(num)) {
|
case FLOAT8OID:
|
||||||
datum_msg->datum_double = numeric_to_double_no_overflow(num);
|
datum_msg->datum_double = DatumGetFloat8(datum);
|
||||||
}
|
datum_msg->has_datum_double = true;
|
||||||
break;
|
break;
|
||||||
case CHAROID:
|
case NUMERICOID:
|
||||||
c = DatumGetChar(datum);
|
num = DatumGetNumeric(datum);
|
||||||
datum_msg->datum_string = &c;
|
if (!numeric_is_nan(num)) {
|
||||||
break;
|
datum_msg->datum_double = numeric_to_double_no_overflow(num);
|
||||||
case VARCHAROID:
|
datum_msg->has_datum_double = true;
|
||||||
case TEXTOID:
|
}
|
||||||
datum_msg->datum_string = DatumGetCString(datum);
|
break;
|
||||||
break;
|
case CHAROID:
|
||||||
case BYTEAOID:
|
c = DatumGetChar(datum);
|
||||||
valptr = DatumGetByteaPCopy(datum);
|
datum_msg->datum_string = &c;
|
||||||
int size = VARSIZE(valptr);
|
break;
|
||||||
datum_msg->datum_bytes = *((ProtobufCBinaryData *)palloc(sizeof(ProtobufCBinaryData)));
|
case VARCHAROID:
|
||||||
datum_msg->datum_bytes.data = (uint8_t *)VARDATA(valptr);
|
case TEXTOID:
|
||||||
datum_msg->datum_bytes.len = size - VARHDRSZ;
|
output = OidOutputFunctionCall(typoutput, datum);
|
||||||
break;
|
datum_msg->datum_string = pnstrdup(output, strlen(output));
|
||||||
default:
|
break;
|
||||||
output = OidOutputFunctionCall(typoutput, datum);
|
case BYTEAOID:
|
||||||
datum_msg->datum_bytes = *((ProtobufCBinaryData *)palloc(sizeof(ProtobufCBinaryData)));
|
valptr = DatumGetByteaPCopy(datum);
|
||||||
datum_msg->datum_bytes.data = (uint8_t *)output;
|
int size = VARSIZE(valptr);
|
||||||
datum_msg->datum_bytes.len = sizeof(output);
|
datum_msg->datum_bytes =
|
||||||
break;
|
*((ProtobufCBinaryData *)palloc(sizeof(ProtobufCBinaryData)));
|
||||||
}
|
datum_msg->datum_bytes.data = (uint8_t *)VARDATA(valptr);
|
||||||
|
datum_msg->datum_bytes.len = size - VARHDRSZ;
|
||||||
|
datum_msg->has_datum_bytes = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
output = OidOutputFunctionCall(typoutput, datum);
|
||||||
|
datum_msg->datum_bytes =
|
||||||
|
*((ProtobufCBinaryData *)palloc(sizeof(ProtobufCBinaryData)));
|
||||||
|
datum_msg->datum_bytes.data = (uint8_t *)output;
|
||||||
|
datum_msg->datum_bytes.len = sizeof(output);
|
||||||
|
datum_msg->has_datum_bytes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Decoderbufs__DatumMessage tuple_to_datum_msg(Relation relation, HeapTuple tuple) {
|
static void tuple_to_tuple_msg(Decoderbufs__DatumMessage **tmsg, Relation relation,
|
||||||
TupleDesc tupdesc = RelationGetDescr(relation);
|
HeapTuple tuple, TupleDesc tupdesc) {
|
||||||
int natt;
|
int natt;
|
||||||
Decoderbufs__DatumMessage datum_msg = DECODERBUFS__DATUM_MESSAGE__INIT;
|
|
||||||
|
|
||||||
/* Build column names and values */
|
/* build column names and values */
|
||||||
for (natt = 0; natt < tupdesc->natts; natt++) {
|
for (natt = 0; natt < tupdesc->natts; natt++) {
|
||||||
Form_pg_attribute attr;
|
Form_pg_attribute attr;
|
||||||
Datum origval;
|
Datum origval;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
|
|
||||||
attr = tupdesc->attrs[natt];
|
attr = tupdesc->attrs[natt];
|
||||||
|
|
||||||
/* Skip dropped columns and system columns */
|
/* skip dropped columns and system columns */
|
||||||
if (attr->attisdropped || attr->attnum < 0)
|
if (attr->attisdropped || attr->attnum < 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the column name */
|
Decoderbufs__DatumMessage datum_msg = DECODERBUFS__DATUM_MESSAGE__INIT;
|
||||||
datum_msg.column_name = quote_identifier(NameStr(attr->attname));
|
|
||||||
|
|
||||||
/* Get Datum from tuple */
|
/* set the column name */
|
||||||
origval = fastgetattr(tuple, natt + 1, tupdesc, &isnull);
|
const char *col_name = quote_identifier(NameStr(attr->attname));
|
||||||
|
datum_msg.column_name = col_name;
|
||||||
|
|
||||||
/* Get output function */
|
/* set datum from tuple */
|
||||||
datum_msg.column_type = attr->atttypid;
|
origval = fastgetattr(tuple, natt + 1, tupdesc, &isnull);
|
||||||
|
|
||||||
Oid typoutput;
|
/* get output function */
|
||||||
bool typisvarlena;
|
datum_msg.column_type = attr->atttypid;
|
||||||
/* Query output function */
|
datum_msg.has_column_type = true;
|
||||||
getTypeOutputInfo(attr->atttypid, &typoutput, &typisvarlena);
|
|
||||||
if (!isnull) {
|
Oid typoutput;
|
||||||
if (typisvarlena && VARATT_IS_EXTERNAL_ONDISK(origval)) {
|
bool typisvarlena;
|
||||||
// what to do if anything?
|
/* Query output function */
|
||||||
} else if (!typisvarlena) {
|
getTypeOutputInfo(attr->atttypid, &typoutput, &typisvarlena);
|
||||||
set_datum_value(&datum_msg, attr->atttypid, typoutput, origval);
|
if (!isnull) {
|
||||||
} else {
|
if (typisvarlena && VARATT_IS_EXTERNAL_ONDISK(origval)) {
|
||||||
Datum val = PointerGetDatum(PG_DETOAST_DATUM(origval));
|
// TODO: Is there a way we can handle this?
|
||||||
set_datum_value(&datum_msg, attr->atttypid, typoutput, val);
|
elog(WARNING, "Not handling external on disk varlena at the moment.");
|
||||||
}
|
} else if (!typisvarlena) {
|
||||||
}
|
set_datum_value(&datum_msg, attr->atttypid, typoutput, origval);
|
||||||
}
|
} else {
|
||||||
|
Datum val = PointerGetDatum(PG_DETOAST_DATUM(origval));
|
||||||
|
set_datum_value(&datum_msg, attr->atttypid, typoutput, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmsg[natt] = palloc(sizeof(datum_msg));
|
||||||
|
memcpy(tmsg[natt], &datum_msg, sizeof(datum_msg));
|
||||||
|
}
|
||||||
|
|
||||||
return datum_msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -305,6 +371,7 @@ static void pg_decode_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
|
||||||
Form_pg_class class_form;
|
Form_pg_class class_form;
|
||||||
char replident = relation->rd_rel->relreplident;
|
char replident = relation->rd_rel->relreplident;
|
||||||
bool is_rel_non_selective;
|
bool is_rel_non_selective;
|
||||||
|
Decoderbufs__RowMessage rmsg = DECODERBUFS__ROW_MESSAGE__INIT;
|
||||||
class_form = RelationGetForm(relation);
|
class_form = RelationGetForm(relation);
|
||||||
|
|
||||||
data = ctx->output_plugin_private;
|
data = ctx->output_plugin_private;
|
||||||
|
@ -314,48 +381,55 @@ static void pg_decode_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
|
||||||
|
|
||||||
RelationGetIndexList(relation);
|
RelationGetIndexList(relation);
|
||||||
is_rel_non_selective = (replident == REPLICA_IDENTITY_NOTHING ||
|
is_rel_non_selective = (replident == REPLICA_IDENTITY_NOTHING ||
|
||||||
(replident == REPLICA_IDENTITY_DEFAULT &&
|
(replident == REPLICA_IDENTITY_DEFAULT &&
|
||||||
!OidIsValid(relation->rd_replidindex)));
|
!OidIsValid(relation->rd_replidindex)));
|
||||||
|
|
||||||
/* set common fields */
|
/* set common fields */
|
||||||
data->txn_msg->table = quote_qualified_identifier(
|
rmsg.commit_time = TIMESTAMPTZ_TO_USEC_SINCE_EPOCH(txn->commit_time);
|
||||||
get_namespace_name(
|
rmsg.has_commit_time = true;
|
||||||
get_rel_namespace(RelationGetRelid(relation))),
|
rmsg.table = quote_qualified_identifier(
|
||||||
NameStr(class_form->relname));
|
get_namespace_name(get_rel_namespace(RelationGetRelid(relation))),
|
||||||
|
NameStr(class_form->relname));
|
||||||
|
|
||||||
/* decode different operation types */
|
/* decode different operation types */
|
||||||
switch (change->action) {
|
switch (change->action) {
|
||||||
case REORDER_BUFFER_CHANGE_INSERT:
|
case REORDER_BUFFER_CHANGE_INSERT:
|
||||||
data->txn_msg->op = DECODERBUFS__OP__INSERT;
|
rmsg.op = DECODERBUFS__OP__INSERT;
|
||||||
|
rmsg.has_op = true;
|
||||||
if (change->data.tp.newtuple != NULL) {
|
if (change->data.tp.newtuple != NULL) {
|
||||||
HeapTupleGetDatum(&change->data.tp.newtuple->tuple);
|
TupleDesc tupdesc = RelationGetDescr(relation);
|
||||||
Decoderbufs__DatumMessage new_datum = tuple_to_datum_msg(relation,
|
rmsg.n_new_tuple = tupdesc->natts;
|
||||||
&change->data.tp.newtuple->tuple);
|
rmsg.new_tuple = palloc(sizeof(Decoderbufs__DatumMessage) * tupdesc->natts);
|
||||||
data->txn_msg->new_datum = &new_datum;
|
tuple_to_tuple_msg(rmsg.new_tuple, relation, &change->data.tp.newtuple->tuple, tupdesc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REORDER_BUFFER_CHANGE_UPDATE:
|
case REORDER_BUFFER_CHANGE_UPDATE:
|
||||||
data->txn_msg->op = DECODERBUFS__OP__UPDATE;
|
rmsg.op = DECODERBUFS__OP__UPDATE;
|
||||||
if (is_rel_non_selective) {
|
rmsg.has_op = true;
|
||||||
if (change->data.tp.oldtuple != NULL) {
|
if (!is_rel_non_selective) {
|
||||||
Decoderbufs__DatumMessage old_datum = tuple_to_datum_msg(relation,
|
if (change->data.tp.oldtuple != NULL) {
|
||||||
&change->data.tp.oldtuple->tuple);
|
TupleDesc tupdesc = RelationGetDescr(relation);
|
||||||
data->txn_msg->old_datum = &old_datum;
|
rmsg.n_old_tuple = tupdesc->natts;
|
||||||
}
|
rmsg.old_tuple = palloc(sizeof(Decoderbufs__DatumMessage) * tupdesc->natts);
|
||||||
if (change->data.tp.newtuple != NULL) {
|
tuple_to_tuple_msg(rmsg.old_tuple, relation, &change->data.tp.oldtuple->tuple, tupdesc);
|
||||||
Decoderbufs__DatumMessage new_datum = tuple_to_datum_msg(relation,
|
}
|
||||||
&change->data.tp.newtuple->tuple);
|
if (change->data.tp.newtuple != NULL) {
|
||||||
data->txn_msg->new_datum = &new_datum;
|
TupleDesc tupdesc = RelationGetDescr(relation);
|
||||||
}
|
rmsg.n_new_tuple = tupdesc->natts;
|
||||||
|
rmsg.new_tuple = palloc(sizeof(Decoderbufs__DatumMessage) * tupdesc->natts);
|
||||||
|
tuple_to_tuple_msg(rmsg.new_tuple, relation, &change->data.tp.newtuple->tuple, tupdesc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REORDER_BUFFER_CHANGE_DELETE:
|
case REORDER_BUFFER_CHANGE_DELETE:
|
||||||
data->txn_msg->op = DECODERBUFS__OP__DELETE;
|
rmsg.op = DECODERBUFS__OP__DELETE;
|
||||||
|
rmsg.has_op = true;
|
||||||
/* if there was no PK, we only know that a delete happened */
|
/* if there was no PK, we only know that a delete happened */
|
||||||
if (is_rel_non_selective && change->data.tp.oldtuple != NULL) {
|
if (!is_rel_non_selective && change->data.tp.oldtuple != NULL) {
|
||||||
Decoderbufs__DatumMessage old_datum = tuple_to_datum_msg(relation,
|
TupleDesc tupdesc = RelationGetDescr(relation);
|
||||||
&change->data.tp.oldtuple->tuple);
|
rmsg.n_old_tuple = tupdesc->natts;
|
||||||
data->txn_msg->old_datum = &old_datum;
|
rmsg.old_tuple = palloc(sizeof(Decoderbufs__DatumMessage) * tupdesc->natts);
|
||||||
|
tuple_to_tuple_msg(rmsg.old_tuple, relation, &change->data.tp.oldtuple->tuple, tupdesc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -363,6 +437,41 @@ static void pg_decode_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->debug_mode) {
|
||||||
|
OutputPluginPrepareWrite(ctx, true);
|
||||||
|
if (rmsg.has_commit_time)
|
||||||
|
appendStringInfo(ctx->out, "commit_time[%" PRId64 "]", rmsg.commit_time);
|
||||||
|
if (rmsg.table)
|
||||||
|
appendStringInfo(ctx->out, ", table[%s]", rmsg.table);
|
||||||
|
if (rmsg.has_op)
|
||||||
|
appendStringInfo(ctx->out, ", op[%d]", rmsg.op);
|
||||||
|
if (rmsg.old_tuple) {
|
||||||
|
appendStringInfo(ctx->out, "\nOLD TUPLE: \n");
|
||||||
|
print_tuple_msg(ctx->out, rmsg.old_tuple, rmsg.n_old_tuple);
|
||||||
|
appendStringInfo(ctx->out, "\n");
|
||||||
|
}
|
||||||
|
if (rmsg.new_tuple) {
|
||||||
|
appendStringInfo(ctx->out, "\nNEW TUPLE: \n");
|
||||||
|
print_tuple_msg(ctx->out, rmsg.new_tuple, rmsg.n_new_tuple);
|
||||||
|
appendStringInfo(ctx->out, "\n");
|
||||||
|
}
|
||||||
|
OutputPluginWrite(ctx, true);
|
||||||
|
} else {
|
||||||
|
OutputPluginPrepareWrite(ctx, true);
|
||||||
|
size_t psize = decoderbufs__row_message__get_packed_size(&rmsg);
|
||||||
|
void *packed = palloc(psize);
|
||||||
|
size_t ssize = decoderbufs__row_message__pack(&rmsg, packed);
|
||||||
|
// appendBinaryStringInfo(ctx->out, (void *)psize, sizeof(psize));
|
||||||
|
appendBinaryStringInfo(ctx->out, packed, ssize);
|
||||||
|
OutputPluginWrite(ctx, true);
|
||||||
|
|
||||||
|
/* free packed buffer */
|
||||||
|
pfree(packed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cleanup msg */
|
||||||
|
free_row_msg_subs(&rmsg);
|
||||||
|
|
||||||
MemoryContextSwitchTo(old);
|
MemoryContextSwitchTo(old);
|
||||||
MemoryContextReset(data->context);
|
MemoryContextReset(data->context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#define PROTOBUF_C__NO_DEPRECATED
|
#define PROTOBUF_C__NO_DEPRECATED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "proto/pg_logicaldec.pb-c.h"
|
#include "pg_logicaldec.pb-c.h"
|
||||||
void decoderbufs__datum_message__init
|
void decoderbufs__datum_message__init
|
||||||
(Decoderbufs__DatumMessage *message)
|
(Decoderbufs__DatumMessage *message)
|
||||||
{
|
{
|
||||||
|
@ -50,47 +50,47 @@ void decoderbufs__datum_message__free_unpacked
|
||||||
assert(message->base.descriptor == &decoderbufs__datum_message__descriptor);
|
assert(message->base.descriptor == &decoderbufs__datum_message__descriptor);
|
||||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||||
}
|
}
|
||||||
void decoderbufs__txn_message__init
|
void decoderbufs__row_message__init
|
||||||
(Decoderbufs__TxnMessage *message)
|
(Decoderbufs__RowMessage *message)
|
||||||
{
|
{
|
||||||
static Decoderbufs__TxnMessage init_value = DECODERBUFS__TXN_MESSAGE__INIT;
|
static Decoderbufs__RowMessage init_value = DECODERBUFS__ROW_MESSAGE__INIT;
|
||||||
*message = init_value;
|
*message = init_value;
|
||||||
}
|
}
|
||||||
size_t decoderbufs__txn_message__get_packed_size
|
size_t decoderbufs__row_message__get_packed_size
|
||||||
(const Decoderbufs__TxnMessage *message)
|
(const Decoderbufs__RowMessage *message)
|
||||||
{
|
{
|
||||||
assert(message->base.descriptor == &decoderbufs__txn_message__descriptor);
|
assert(message->base.descriptor == &decoderbufs__row_message__descriptor);
|
||||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||||
}
|
}
|
||||||
size_t decoderbufs__txn_message__pack
|
size_t decoderbufs__row_message__pack
|
||||||
(const Decoderbufs__TxnMessage *message,
|
(const Decoderbufs__RowMessage *message,
|
||||||
uint8_t *out)
|
uint8_t *out)
|
||||||
{
|
{
|
||||||
assert(message->base.descriptor == &decoderbufs__txn_message__descriptor);
|
assert(message->base.descriptor == &decoderbufs__row_message__descriptor);
|
||||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||||
}
|
}
|
||||||
size_t decoderbufs__txn_message__pack_to_buffer
|
size_t decoderbufs__row_message__pack_to_buffer
|
||||||
(const Decoderbufs__TxnMessage *message,
|
(const Decoderbufs__RowMessage *message,
|
||||||
ProtobufCBuffer *buffer)
|
ProtobufCBuffer *buffer)
|
||||||
{
|
{
|
||||||
assert(message->base.descriptor == &decoderbufs__txn_message__descriptor);
|
assert(message->base.descriptor == &decoderbufs__row_message__descriptor);
|
||||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||||
}
|
}
|
||||||
Decoderbufs__TxnMessage *
|
Decoderbufs__RowMessage *
|
||||||
decoderbufs__txn_message__unpack
|
decoderbufs__row_message__unpack
|
||||||
(ProtobufCAllocator *allocator,
|
(ProtobufCAllocator *allocator,
|
||||||
size_t len,
|
size_t len,
|
||||||
const uint8_t *data)
|
const uint8_t *data)
|
||||||
{
|
{
|
||||||
return (Decoderbufs__TxnMessage *)
|
return (Decoderbufs__RowMessage *)
|
||||||
protobuf_c_message_unpack (&decoderbufs__txn_message__descriptor,
|
protobuf_c_message_unpack (&decoderbufs__row_message__descriptor,
|
||||||
allocator, len, data);
|
allocator, len, data);
|
||||||
}
|
}
|
||||||
void decoderbufs__txn_message__free_unpacked
|
void decoderbufs__row_message__free_unpacked
|
||||||
(Decoderbufs__TxnMessage *message,
|
(Decoderbufs__RowMessage *message,
|
||||||
ProtobufCAllocator *allocator)
|
ProtobufCAllocator *allocator)
|
||||||
{
|
{
|
||||||
assert(message->base.descriptor == &decoderbufs__txn_message__descriptor);
|
assert(message->base.descriptor == &decoderbufs__row_message__descriptor);
|
||||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||||
}
|
}
|
||||||
static const ProtobufCFieldDescriptor decoderbufs__datum_message__field_descriptors[9] =
|
static const ProtobufCFieldDescriptor decoderbufs__datum_message__field_descriptors[9] =
|
||||||
|
@ -235,27 +235,15 @@ const ProtobufCMessageDescriptor decoderbufs__datum_message__descriptor =
|
||||||
(ProtobufCMessageInit) decoderbufs__datum_message__init,
|
(ProtobufCMessageInit) decoderbufs__datum_message__init,
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
NULL,NULL,NULL /* reserved[123] */
|
||||||
};
|
};
|
||||||
static const ProtobufCFieldDescriptor decoderbufs__txn_message__field_descriptors[6] =
|
static const ProtobufCFieldDescriptor decoderbufs__row_message__field_descriptors[5] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"timestamp",
|
"commit_time",
|
||||||
1,
|
1,
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
PROTOBUF_C_LABEL_OPTIONAL,
|
||||||
PROTOBUF_C_TYPE_SINT64,
|
PROTOBUF_C_TYPE_SINT64,
|
||||||
offsetof(Decoderbufs__TxnMessage, has_timestamp),
|
offsetof(Decoderbufs__RowMessage, has_commit_time),
|
||||||
offsetof(Decoderbufs__TxnMessage, timestamp),
|
offsetof(Decoderbufs__RowMessage, commit_time),
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
0, /* flags */
|
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"xid",
|
|
||||||
2,
|
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
|
||||||
PROTOBUF_C_TYPE_INT64,
|
|
||||||
offsetof(Decoderbufs__TxnMessage, has_xid),
|
|
||||||
offsetof(Decoderbufs__TxnMessage, xid),
|
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
0, /* flags */
|
0, /* flags */
|
||||||
|
@ -263,11 +251,11 @@ static const ProtobufCFieldDescriptor decoderbufs__txn_message__field_descriptor
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"table",
|
"table",
|
||||||
3,
|
2,
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
PROTOBUF_C_LABEL_OPTIONAL,
|
||||||
PROTOBUF_C_TYPE_STRING,
|
PROTOBUF_C_TYPE_STRING,
|
||||||
0, /* quantifier_offset */
|
0, /* quantifier_offset */
|
||||||
offsetof(Decoderbufs__TxnMessage, table),
|
offsetof(Decoderbufs__RowMessage, table),
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
0, /* flags */
|
0, /* flags */
|
||||||
|
@ -275,67 +263,66 @@ static const ProtobufCFieldDescriptor decoderbufs__txn_message__field_descriptor
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"op",
|
"op",
|
||||||
4,
|
3,
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
PROTOBUF_C_LABEL_OPTIONAL,
|
||||||
PROTOBUF_C_TYPE_ENUM,
|
PROTOBUF_C_TYPE_ENUM,
|
||||||
offsetof(Decoderbufs__TxnMessage, has_op),
|
offsetof(Decoderbufs__RowMessage, has_op),
|
||||||
offsetof(Decoderbufs__TxnMessage, op),
|
offsetof(Decoderbufs__RowMessage, op),
|
||||||
&decoderbufs__op__descriptor,
|
&decoderbufs__op__descriptor,
|
||||||
NULL,
|
NULL,
|
||||||
0, /* flags */
|
0, /* flags */
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"new_datum",
|
"new_tuple",
|
||||||
5,
|
4,
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
PROTOBUF_C_LABEL_REPEATED,
|
||||||
PROTOBUF_C_TYPE_MESSAGE,
|
PROTOBUF_C_TYPE_MESSAGE,
|
||||||
0, /* quantifier_offset */
|
offsetof(Decoderbufs__RowMessage, n_new_tuple),
|
||||||
offsetof(Decoderbufs__TxnMessage, new_datum),
|
offsetof(Decoderbufs__RowMessage, new_tuple),
|
||||||
&decoderbufs__datum_message__descriptor,
|
&decoderbufs__datum_message__descriptor,
|
||||||
NULL,
|
NULL,
|
||||||
0, /* flags */
|
0, /* flags */
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"old_datum",
|
"old_tuple",
|
||||||
6,
|
5,
|
||||||
PROTOBUF_C_LABEL_OPTIONAL,
|
PROTOBUF_C_LABEL_REPEATED,
|
||||||
PROTOBUF_C_TYPE_MESSAGE,
|
PROTOBUF_C_TYPE_MESSAGE,
|
||||||
0, /* quantifier_offset */
|
offsetof(Decoderbufs__RowMessage, n_old_tuple),
|
||||||
offsetof(Decoderbufs__TxnMessage, old_datum),
|
offsetof(Decoderbufs__RowMessage, old_tuple),
|
||||||
&decoderbufs__datum_message__descriptor,
|
&decoderbufs__datum_message__descriptor,
|
||||||
NULL,
|
NULL,
|
||||||
0, /* flags */
|
0, /* flags */
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
static const unsigned decoderbufs__txn_message__field_indices_by_name[] = {
|
static const unsigned decoderbufs__row_message__field_indices_by_name[] = {
|
||||||
4, /* field[4] = new_datum */
|
0, /* field[0] = commit_time */
|
||||||
5, /* field[5] = old_datum */
|
3, /* field[3] = new_tuple */
|
||||||
3, /* field[3] = op */
|
4, /* field[4] = old_tuple */
|
||||||
2, /* field[2] = table */
|
2, /* field[2] = op */
|
||||||
0, /* field[0] = timestamp */
|
1, /* field[1] = table */
|
||||||
1, /* field[1] = xid */
|
|
||||||
};
|
};
|
||||||
static const ProtobufCIntRange decoderbufs__txn_message__number_ranges[1 + 1] =
|
static const ProtobufCIntRange decoderbufs__row_message__number_ranges[1 + 1] =
|
||||||
{
|
{
|
||||||
{ 1, 0 },
|
{ 1, 0 },
|
||||||
{ 0, 6 }
|
{ 0, 5 }
|
||||||
};
|
};
|
||||||
const ProtobufCMessageDescriptor decoderbufs__txn_message__descriptor =
|
const ProtobufCMessageDescriptor decoderbufs__row_message__descriptor =
|
||||||
{
|
{
|
||||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||||
"decoderbufs.TxnMessage",
|
"decoderbufs.RowMessage",
|
||||||
"TxnMessage",
|
"RowMessage",
|
||||||
"Decoderbufs__TxnMessage",
|
"Decoderbufs__RowMessage",
|
||||||
"decoderbufs",
|
"decoderbufs",
|
||||||
sizeof(Decoderbufs__TxnMessage),
|
sizeof(Decoderbufs__RowMessage),
|
||||||
6,
|
5,
|
||||||
decoderbufs__txn_message__field_descriptors,
|
decoderbufs__row_message__field_descriptors,
|
||||||
decoderbufs__txn_message__field_indices_by_name,
|
decoderbufs__row_message__field_indices_by_name,
|
||||||
1, decoderbufs__txn_message__number_ranges,
|
1, decoderbufs__row_message__number_ranges,
|
||||||
(ProtobufCMessageInit) decoderbufs__txn_message__init,
|
(ProtobufCMessageInit) decoderbufs__row_message__init,
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
NULL,NULL,NULL /* reserved[123] */
|
||||||
};
|
};
|
||||||
const ProtobufCEnumValue decoderbufs__op__enum_values_by_number[3] =
|
const ProtobufCEnumValue decoderbufs__op__enum_values_by_number[3] =
|
||||||
|
|
|
@ -16,7 +16,7 @@ PROTOBUF_C__BEGIN_DECLS
|
||||||
|
|
||||||
|
|
||||||
typedef struct _Decoderbufs__DatumMessage Decoderbufs__DatumMessage;
|
typedef struct _Decoderbufs__DatumMessage Decoderbufs__DatumMessage;
|
||||||
typedef struct _Decoderbufs__TxnMessage Decoderbufs__TxnMessage;
|
typedef struct _Decoderbufs__RowMessage Decoderbufs__RowMessage;
|
||||||
|
|
||||||
|
|
||||||
/* --- enums --- */
|
/* --- enums --- */
|
||||||
|
@ -55,22 +55,22 @@ struct _Decoderbufs__DatumMessage
|
||||||
, NULL, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, NULL, 0,{0,NULL} }
|
, NULL, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, NULL, 0,{0,NULL} }
|
||||||
|
|
||||||
|
|
||||||
struct _Decoderbufs__TxnMessage
|
struct _Decoderbufs__RowMessage
|
||||||
{
|
{
|
||||||
ProtobufCMessage base;
|
ProtobufCMessage base;
|
||||||
protobuf_c_boolean has_timestamp;
|
protobuf_c_boolean has_commit_time;
|
||||||
int64_t timestamp;
|
int64_t commit_time;
|
||||||
protobuf_c_boolean has_xid;
|
|
||||||
int64_t xid;
|
|
||||||
char *table;
|
char *table;
|
||||||
protobuf_c_boolean has_op;
|
protobuf_c_boolean has_op;
|
||||||
Decoderbufs__Op op;
|
Decoderbufs__Op op;
|
||||||
Decoderbufs__DatumMessage *new_datum;
|
size_t n_new_tuple;
|
||||||
Decoderbufs__DatumMessage *old_datum;
|
Decoderbufs__DatumMessage **new_tuple;
|
||||||
|
size_t n_old_tuple;
|
||||||
|
Decoderbufs__DatumMessage **old_tuple;
|
||||||
};
|
};
|
||||||
#define DECODERBUFS__TXN_MESSAGE__INIT \
|
#define DECODERBUFS__ROW_MESSAGE__INIT \
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&decoderbufs__txn_message__descriptor) \
|
{ PROTOBUF_C_MESSAGE_INIT (&decoderbufs__row_message__descriptor) \
|
||||||
, 0,0, 0,0, NULL, 0,0, NULL, NULL }
|
, 0,0, NULL, 0,0, 0,NULL, 0,NULL }
|
||||||
|
|
||||||
|
|
||||||
/* Decoderbufs__DatumMessage methods */
|
/* Decoderbufs__DatumMessage methods */
|
||||||
|
@ -92,32 +92,32 @@ Decoderbufs__DatumMessage *
|
||||||
void decoderbufs__datum_message__free_unpacked
|
void decoderbufs__datum_message__free_unpacked
|
||||||
(Decoderbufs__DatumMessage *message,
|
(Decoderbufs__DatumMessage *message,
|
||||||
ProtobufCAllocator *allocator);
|
ProtobufCAllocator *allocator);
|
||||||
/* Decoderbufs__TxnMessage methods */
|
/* Decoderbufs__RowMessage methods */
|
||||||
void decoderbufs__txn_message__init
|
void decoderbufs__row_message__init
|
||||||
(Decoderbufs__TxnMessage *message);
|
(Decoderbufs__RowMessage *message);
|
||||||
size_t decoderbufs__txn_message__get_packed_size
|
size_t decoderbufs__row_message__get_packed_size
|
||||||
(const Decoderbufs__TxnMessage *message);
|
(const Decoderbufs__RowMessage *message);
|
||||||
size_t decoderbufs__txn_message__pack
|
size_t decoderbufs__row_message__pack
|
||||||
(const Decoderbufs__TxnMessage *message,
|
(const Decoderbufs__RowMessage *message,
|
||||||
uint8_t *out);
|
uint8_t *out);
|
||||||
size_t decoderbufs__txn_message__pack_to_buffer
|
size_t decoderbufs__row_message__pack_to_buffer
|
||||||
(const Decoderbufs__TxnMessage *message,
|
(const Decoderbufs__RowMessage *message,
|
||||||
ProtobufCBuffer *buffer);
|
ProtobufCBuffer *buffer);
|
||||||
Decoderbufs__TxnMessage *
|
Decoderbufs__RowMessage *
|
||||||
decoderbufs__txn_message__unpack
|
decoderbufs__row_message__unpack
|
||||||
(ProtobufCAllocator *allocator,
|
(ProtobufCAllocator *allocator,
|
||||||
size_t len,
|
size_t len,
|
||||||
const uint8_t *data);
|
const uint8_t *data);
|
||||||
void decoderbufs__txn_message__free_unpacked
|
void decoderbufs__row_message__free_unpacked
|
||||||
(Decoderbufs__TxnMessage *message,
|
(Decoderbufs__RowMessage *message,
|
||||||
ProtobufCAllocator *allocator);
|
ProtobufCAllocator *allocator);
|
||||||
/* --- per-message closures --- */
|
/* --- per-message closures --- */
|
||||||
|
|
||||||
typedef void (*Decoderbufs__DatumMessage_Closure)
|
typedef void (*Decoderbufs__DatumMessage_Closure)
|
||||||
(const Decoderbufs__DatumMessage *message,
|
(const Decoderbufs__DatumMessage *message,
|
||||||
void *closure_data);
|
void *closure_data);
|
||||||
typedef void (*Decoderbufs__TxnMessage_Closure)
|
typedef void (*Decoderbufs__RowMessage_Closure)
|
||||||
(const Decoderbufs__TxnMessage *message,
|
(const Decoderbufs__RowMessage *message,
|
||||||
void *closure_data);
|
void *closure_data);
|
||||||
|
|
||||||
/* --- services --- */
|
/* --- services --- */
|
||||||
|
@ -127,7 +127,7 @@ typedef void (*Decoderbufs__TxnMessage_Closure)
|
||||||
|
|
||||||
extern const ProtobufCEnumDescriptor decoderbufs__op__descriptor;
|
extern const ProtobufCEnumDescriptor decoderbufs__op__descriptor;
|
||||||
extern const ProtobufCMessageDescriptor decoderbufs__datum_message__descriptor;
|
extern const ProtobufCMessageDescriptor decoderbufs__datum_message__descriptor;
|
||||||
extern const ProtobufCMessageDescriptor decoderbufs__txn_message__descriptor;
|
extern const ProtobufCMessageDescriptor decoderbufs__row_message__descriptor;
|
||||||
|
|
||||||
PROTOBUF_C__END_DECLS
|
PROTOBUF_C__END_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue