Пример #1
0
/* Discard accumulated COPY line */
static void
CopyClear(void)
{
	/* Make sure init is done */
	CopyAppend(NULL);

	resetStringInfo(&copyString);
}
Пример #2
0
/* Output and then clear accumulated COPY line */
static void
CopyFlush(void)
{
	/* Make sure init is done */
	CopyAppend(NULL);

	printf("COPY: %s\n", copyString.data);
	CopyClear();
}
Пример #3
0
/* Decode a bool type */
static int
decode_bool(const char *buffer, unsigned int buff_size, unsigned int *out_size)
{
	if (buff_size < sizeof(bool))
		return -1;

	CopyAppend(*(bool *) buffer ? "t" : "f");
	*out_size = sizeof(bool);
	return 0;
}
Пример #4
0
void CutAppend( LPCLASSDATA lpcd )
{
	/*
	 *	Append the selection to the clipboard.
	 */
	if ( CopyAppend( lpcd ))
		/*
		 *	Cut it.
		 */
		 Delete( lpcd );
}
Пример #5
0
/*
 * Try to decode a tuple using a types string provided previously.
 *
 * Arguments:
 *   tupleData   - pointer to the tuple data
 *   tupleSize   - tuple size in bytes
 */
void
FormatDecode(const char *tupleData, unsigned int tupleSize)
{
	HeapTupleHeader header = (HeapTupleHeader) tupleData;
	const char *data = tupleData + header->t_hoff;
	unsigned int size = tupleSize - header->t_hoff;
	int			curr_attr;

	CopyClear();

	for (curr_attr = 0; curr_attr < ncallbacks; curr_attr++)
	{
		int			ret;
		unsigned int processed_size = 0;

		if ((header->t_infomask & HEAP_HASNULL) && att_isnull(curr_attr, header->t_bits))
		{
			CopyAppend("\\N");
			continue;
		}

		if (size <= 0)
		{
			printf("Error: unable to decode a tuple, no more bytes left. Partial data: %s\n",
				   copyString.data);
			return;
		}

		ret = callbacks[curr_attr] (data, size, &processed_size);
		if (ret < 0)
		{
			printf("Error: unable to decode a tuple, callback #%d returned %d. Partial data: %s\n",
				   curr_attr + 1, ret, copyString.data);
			return;
		}

		size -= processed_size;
		data += processed_size;
	}

	if (size != 0)
	{
		printf("Error: unable to decode a tuple, %d bytes left, 0 expected. Partial data: %s\n",
			   size, copyString.data);
		return;
	}

	CopyFlush();
}
Пример #6
0
static int
ReadStringFromToast(const char *buffer,
		unsigned int buff_size,
		unsigned int* out_size)
{
	int		result = 0;

	/* If toasted value is on disk, we'll try to restore it. */
	if (VARATT_IS_EXTERNAL_ONDISK(buffer))
	{
		varatt_external toast_ptr;
		char	   *toast_data = NULL;
		/* Number of chunks the TOAST data is divided into */
		int32		num_chunks;
		/* Actual size of external TOASTed value */
		int32		toast_ext_size;
		/* Path to directory with TOAST realtion file */
		char	   *toast_relation_path;
		/* Filename of TOAST relation file */
		char		toast_relation_filename[MAXPGPATH];
		FILE	   *toast_rel_fp;
		unsigned int block_options = 0;
		unsigned int control_options = 0;

		VARATT_EXTERNAL_GET_POINTER(toast_ptr, buffer);
		printf("  TOAST value. Raw size: %8d, external size: %8d, "
				"value id: %6d, toast relation id: %6d\n",
				toast_ptr.va_rawsize,
				toast_ptr.va_extsize,
				toast_ptr.va_valueid,
				toast_ptr.va_toastrelid);

		/* Extract TOASTed value */
		toast_ext_size = toast_ptr.va_extsize;
		num_chunks = (toast_ext_size - 1) / TOAST_MAX_CHUNK_SIZE + 1;
		printf("  Number of chunks: %d\n", num_chunks);

		/* Open TOAST relation file */
		toast_relation_path = strdup(fileName);
		get_parent_directory(toast_relation_path);
		sprintf(toast_relation_filename, "%s/%d", toast_relation_path,
				toast_ptr.va_toastrelid);
		printf("  Read TOAST relation %s\n", toast_relation_filename);
		toast_rel_fp = fopen(toast_relation_filename, "rb");
		if (!toast_rel_fp) {
			printf("Cannot open TOAST relation %s\n",
					toast_relation_filename);
			result = -1;
		}

		if (result == 0)
		{
			unsigned int toast_relation_block_size = GetBlockSize(toast_rel_fp);
			fseek(toast_rel_fp, 0, SEEK_SET);
			toast_data = malloc(toast_ptr.va_rawsize);

			result = DumpFileContents(block_options,
					control_options,
					toast_rel_fp,
					toast_relation_block_size,
					-1, /* no start block */
					-1, /* no end block */
					true, /* is toast relation */
					toast_ptr.va_valueid,
					toast_ptr.va_extsize,
					toast_data);

			if (result == 0)
			{
				if (VARATT_EXTERNAL_IS_COMPRESSED(toast_ptr))
					result = DumpCompressedString(toast_data, toast_ext_size);
				else
					CopyAppendEncode(toast_data, toast_ext_size);
			}
			else
			{
				printf("Error in TOAST file.\n");
			}

			free(toast_data);
		}

		fclose(toast_rel_fp);
		free(toast_relation_path);
	}
	/* If tag is indirect or expanded, it was stored in memory. */
	else
	{
		CopyAppend("(TOASTED IN MEMORY)");
	}

	return result;
}
Пример #7
0
/* Decode char(N), varchar(N), text, json or xml types */
static int
decode_string(const char *buffer, unsigned int buff_size, unsigned int *out_size)
{
	int			padding = 0;

	/* Skip padding bytes. */
	while (*buffer == 0x00)
	{
		if (buff_size == 0)
			return -1;

		buff_size--;
		buffer++;
		padding++;
	}

	if (VARATT_IS_1B_E(buffer))
	{
		/*
		 * 00000001 1-byte length word, unaligned, TOAST pointer
		 */
		uint32		len = VARSIZE_EXTERNAL(buffer);
		int			result = 0;

		if (len > buff_size)
			return -1;

		if (blockOptions & BLOCK_DECODE_TOAST)
		{
			result = ReadStringFromToast(buffer, buff_size, out_size);
		}
		else
		{
			CopyAppend("(TOASTED)");
		}

		*out_size = padding + len;
		return result;
	}

	if (VARATT_IS_1B(buffer))
	{
		/*
		 * xxxxxxx1 1-byte length word, unaligned, uncompressed data (up to
		 * 126b) xxxxxxx is 1 + string length
		 */
		uint8		len = VARSIZE_1B(buffer);

		if (len > buff_size)
			return -1;

		CopyAppendEncode(buffer + 1, len - 1);
		*out_size = padding + len;
		return 0;
	}

	if (VARATT_IS_4B_U(buffer) && buff_size >= 4)
	{
		/*
		 * xxxxxx00 4-byte length word, aligned, uncompressed data (up to 1G)
		 */
		uint32		len = VARSIZE_4B(buffer);

		if (len > buff_size)
			return -1;

		CopyAppendEncode(buffer + 4, len - 4);
		*out_size = padding + len;
		return 0;
	}

	if (VARATT_IS_4B_C(buffer) && buff_size >= 8)
	{
		/*
		 * xxxxxx10 4-byte length word, aligned, *compressed* data (up to 1G)
		 */
		int			decompress_ret;
		uint32		len = VARSIZE_4B(buffer);
		uint32		decompressed_len = VARRAWSIZE_4B_C(buffer);

		if (len > buff_size)
			return -1;

		if (decompressed_len > sizeof(decompress_tmp_buff))
		{
			printf("WARNING: Unable to decompress a string since it's too "
				   "large (%d bytes after decompressing). Consider increasing "
				   "decompress_tmp_buff size.\n", decompressed_len);

			CopyAppend("(COMPRESSED)");
			*out_size = padding + len;
			return 0;
		}

		decompress_ret = pglz_decompress(VARDATA_4B_C(buffer), len - 2 * sizeof(uint32),
										 decompress_tmp_buff, decompressed_len);
		if ((decompress_ret != decompressed_len) || (decompress_ret < 0))
		{
			printf("WARNING: Unable to decompress a string. Data is corrupted.\n");
			CopyAppend("(COMPRESSED)");
			*out_size = padding + len;
			return 0;
		}

		CopyAppendEncode(decompress_tmp_buff, decompressed_len);
		*out_size = padding + len;
		return 0;
	}

	return -9;
}
Пример #8
0
/*
 * Append given string to current COPY line and encode special symbols
 * like \r, \n, \t and \\.
 */
static void
CopyAppendEncode(const char *str, int orig_len)
{
	/*
	 * Should be enough in most cases. If it's not user can manually change
	 * this limit. Unfortunately there is no way to know how much memory user
	 * is willing to allocate.
	 */
	static char tmp_buff[64 * 1024];

	/* Reserve one byte for a trailing zero. */
	const int	max_offset = sizeof(tmp_buff) - 2;
	int			curr_offset = 0;
	int			len = orig_len;

	while (len > 0)
	{
		/*
		 * Make sure there is enough free space for at least one special
		 * symbol and a trailing zero.
		 */
		if (curr_offset > max_offset - 2)
		{
			printf("ERROR: Unable to properly encode a string since it's too "
				   "large (%d bytes). Try to increase tmp_buff size in CopyAppendEncode "
				   "procedure.\n", orig_len);
			exit(1);
		}

		/*
		 * Since we are working with potentially corrupted data we can
		 * encounter \0 as well.
		 */
		if (*str == '\0')
		{
			tmp_buff[curr_offset] = '\\';
			tmp_buff[curr_offset + 1] = '0';
			curr_offset += 2;
		}
		else if (*str == '\r')
		{
			tmp_buff[curr_offset] = '\\';
			tmp_buff[curr_offset + 1] = 'r';
			curr_offset += 2;
		}
		else if (*str == '\n')
		{
			tmp_buff[curr_offset] = '\\';
			tmp_buff[curr_offset + 1] = 'n';
			curr_offset += 2;
		}
		else if (*str == '\t')
		{
			tmp_buff[curr_offset] = '\\';
			tmp_buff[curr_offset + 1] = 'r';
			curr_offset += 2;
		}
		else if (*str == '\\')
		{
			tmp_buff[curr_offset] = '\\';
			tmp_buff[curr_offset + 1] = '\\';
			curr_offset += 2;
		}
		else
		{
			/* It's a regular symbol. */
			tmp_buff[curr_offset] = *str;
			curr_offset++;
		}

		str++;
		len--;
	}

	tmp_buff[curr_offset] = '\0';
	CopyAppend(tmp_buff);
}