odyssey/shapito/be_write.h

364 lines
11 KiB
C

#ifndef SHAPITO_BE_WRITE_H
#define SHAPITO_BE_WRITE_H
/*
* Shapito.
*
* Protocol-level PostgreSQL client library.
*/
SHAPITO_API static inline int
shapito_be_write_error_as(shapito_stream_t *stream, char *severity, char *code,
char *detail, int detail_len,
char *hint, int hint_len,
char *message, int len)
{
int size = 1 /* S */ + 6 +
1 /* C */ + 6 +
1 /* M */ + len + 1 +
1 /* zero */;
if (detail && detail_len > 0)
size += 1 + /* D */ + detail_len + 1;
if (hint && hint_len > 0)
size += 1 + /* H */ + hint_len + 1;
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + size);
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'E');
shapito_stream_write32(stream, sizeof(uint32_t) + size);
shapito_stream_write8(stream, 'S');
shapito_stream_write(stream, severity, 6);
shapito_stream_write8(stream, 'C');
shapito_stream_write(stream, code, 6);
if (detail && detail_len > 0) {
shapito_stream_write8(stream, 'D');
shapito_stream_write(stream, detail, detail_len);
shapito_stream_write8(stream, 0);
}
if (hint && hint_len > 0) {
shapito_stream_write8(stream, 'H');
shapito_stream_write(stream, hint, hint_len);
shapito_stream_write8(stream, 0);
}
shapito_stream_write8(stream, 'M');
shapito_stream_write(stream, message, len);
shapito_stream_write8(stream, 0);
shapito_stream_write8(stream, 0);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_error(shapito_stream_t *stream, char *code, char *message, int len)
{
return shapito_be_write_error_as(stream, "ERROR", code, NULL, 0, NULL, 0, message, len);
}
SHAPITO_API static inline int
shapito_be_write_error_fatal(shapito_stream_t *stream, char *code, char *message, int len)
{
return shapito_be_write_error_as(stream, "FATAL", code, NULL, 0, NULL, 0, message, len);
}
SHAPITO_API static inline int
shapito_be_write_error_panic(shapito_stream_t *stream, char *code, char *message, int len)
{
return shapito_be_write_error_as(stream, "PANIC", code, NULL, 0, NULL, 0, message, len);
}
SHAPITO_API static inline int
shapito_be_write_notice(shapito_stream_t *stream, char *message, int len)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + len + 1);
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'N');
shapito_stream_write32(stream, sizeof(uint32_t) + len);
shapito_stream_write(stream, message, len);
shapito_stream_write8(stream, 0);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_authentication_ok(shapito_stream_t *stream)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + sizeof(uint32_t));
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'R');
shapito_stream_write32(stream, sizeof(uint32_t) + sizeof(uint32_t));
shapito_stream_write32(stream, 0);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_authentication_clear_text(shapito_stream_t *stream)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + sizeof(uint32_t));
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'R');
shapito_stream_write32(stream, sizeof(uint32_t) + sizeof(uint32_t));
shapito_stream_write32(stream, 3);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_authentication_md5(shapito_stream_t *stream, char salt[4])
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + sizeof(uint32_t) + 4);
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'R');
shapito_stream_write32(stream, sizeof(uint32_t) + sizeof(uint32_t) + 4);
shapito_stream_write32(stream, 5);
shapito_stream_write(stream, salt, 4);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_backend_key_data(shapito_stream_t *stream, uint32_t pid, uint32_t key)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) +
sizeof(uint32_t) +
sizeof(uint32_t));
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'K');
shapito_stream_write32(stream, sizeof(uint32_t) + sizeof(uint32_t) +
sizeof(uint32_t));
shapito_stream_write32(stream, pid);
shapito_stream_write32(stream, key);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_parameter_status(shapito_stream_t *stream, char *key, int key_len,
char *value, int value_len)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + key_len + value_len);
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'S');
shapito_stream_write32(stream, sizeof(uint32_t) + key_len + value_len);
shapito_stream_write(stream, key, key_len);
shapito_stream_write(stream, value, value_len);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_ready(shapito_stream_t *stream, uint8_t status)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + sizeof(uint8_t));
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'Z');
shapito_stream_write32(stream, sizeof(uint32_t) + sizeof(uint8_t));
shapito_stream_write8(stream, status);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_row_description(shapito_stream_t *stream)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + sizeof(uint16_t));
if (shapito_unlikely(rc == -1))
return -1;
int position = shapito_stream_used(stream);
shapito_stream_write8(stream, 'T');
shapito_stream_write32(stream, sizeof(uint32_t) + sizeof(uint16_t));
shapito_stream_write16(stream, 0);
return position;
}
SHAPITO_API static inline int
shapito_be_write_row_description_add(shapito_stream_t *stream, int start,
char *name, int name_len,
int32_t table_id,
int16_t attrnum,
int32_t type_id,
int16_t type_size,
int32_t type_modifier,
int32_t format_code)
{
int size = name_len + 1 +
sizeof(uint32_t) /* table_id */+
sizeof(uint16_t) /* attrnum */ +
sizeof(uint32_t) /* type_id */ +
sizeof(uint16_t) /* type_size */ +
sizeof(uint32_t) /* type_modifier */ +
sizeof(uint16_t) /* format_code */;
int rc = shapito_stream_ensure(stream, size);
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write(stream, name, name_len);
shapito_stream_write8(stream, 0);
shapito_stream_write32(stream, table_id);
shapito_stream_write16(stream, attrnum);
shapito_stream_write32(stream, type_id);
shapito_stream_write16(stream, type_size);
shapito_stream_write32(stream, type_modifier);
shapito_stream_write16(stream, format_code);
shapito_header_t *header;
header = (shapito_header_t*)(stream->start + start);
uint32_t pos_size = sizeof(uint32_t) + sizeof(uint16_t);
char *pos = (char*)&header->len;
uint32_t total_size;
uint16_t count;
shapito_stream_read32(&total_size, &pos, &pos_size);
shapito_stream_read16(&count, &pos, &pos_size);
total_size += size;
count++;
shapito_stream_write32to((char*)&header->len, total_size);
shapito_stream_write16to((char*)&header->len + sizeof(uint32_t), count);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_row_descriptionf(shapito_stream_t *stream, char *fmt, ...)
{
int offset;
offset = shapito_be_write_row_description(stream);
if (shapito_unlikely(offset == -1))
return -1;
va_list args;
va_start(args, fmt);
while (*fmt) {
char *name = va_arg(args, char*);
int name_len = strlen(name);
int rc;
switch (*fmt) {
case 's':
rc = shapito_be_write_row_description_add(stream, offset, name, name_len,
0, 0, 25 /* TEXTOID */, -1, 0, 0);
break;
case 'd':
rc = shapito_be_write_row_description_add(stream, offset, name, name_len,
0, 0, 23 /* INT4OID */, 4, 0, 0);
break;
case 'l':
rc = shapito_be_write_row_description_add(stream, offset, name, name_len,
0, 0, 20 /* INT8OID */, 8, 0, 0);
break;
default:
va_end(args);
return -1;
}
if (rc == -1)
return -1;
fmt++;
}
va_end(args);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_data_row(shapito_stream_t *stream)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + sizeof(uint16_t));
if (shapito_unlikely(rc == -1))
return -1;
int position = shapito_stream_used(stream);
shapito_stream_write8(stream, 'D');
shapito_stream_write32(stream, sizeof(uint32_t) + sizeof(uint16_t));
shapito_stream_write16(stream, 0);
return position;
}
SHAPITO_API static inline int
shapito_be_write_data_row_add(shapito_stream_t *stream, int start, char *data, int32_t len)
{
int is_null = len == -1;
int size = sizeof(uint32_t) + (is_null ? 0 : len);
int rc = shapito_stream_ensure(stream, size);
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write32(stream, len);
if (! is_null)
shapito_stream_write(stream, data, len);
shapito_header_t *header;
header = (shapito_header_t*)(stream->start + start);
uint32_t pos_size = sizeof(uint32_t) + sizeof(uint16_t);
char *pos = (char*)&header->len;
uint32_t total_size;
uint16_t count;
shapito_stream_read32(&total_size, &pos, &pos_size);
shapito_stream_read16(&count, &pos, &pos_size);
total_size += size;
count++;
shapito_stream_write32to((char*)&header->len, total_size);
shapito_stream_write16to((char*)&header->len + sizeof(uint32_t), count);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_complete(shapito_stream_t *stream, char *message, int len)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t) + len);
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'C');
shapito_stream_write32(stream, sizeof(uint32_t) + len);
shapito_stream_write(stream, message, len);
return 0;
}
SHAPITO_API static inline int
shapito_be_write_empty_query(shapito_stream_t *stream)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t));
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'I');
shapito_stream_write32(stream, sizeof(uint32_t));
return 0;
}
SHAPITO_API static inline int
shapito_be_write_parse_complete(shapito_stream_t *stream)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t));
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, '1');
shapito_stream_write32(stream, sizeof(uint32_t));
return 0;
}
SHAPITO_API static inline int
shapito_be_write_bind_complete(shapito_stream_t *stream)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t));
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, '2');
shapito_stream_write32(stream, sizeof(uint32_t));
return 0;
}
SHAPITO_API static inline int
shapito_be_write_portal_suspended(shapito_stream_t *stream)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t));
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 's');
shapito_stream_write32(stream, sizeof(uint32_t));
return 0;
}
SHAPITO_API static inline int
shapito_be_write_no_data(shapito_stream_t *stream)
{
int rc = shapito_stream_ensure(stream, sizeof(shapito_header_t));
if (shapito_unlikely(rc == -1))
return -1;
shapito_stream_write8(stream, 'n');
shapito_stream_write32(stream, sizeof(uint32_t));
return 0;
}
#endif /* SHAPITO_BE_WRITE_H */