1 /*-------------------------------------------------------------------------
2  *
3  * columnar.c
4  *
5  * This file contains...
6  *
7  * Copyright (c) 2016, Citus Data, Inc.
8  *
9  * $Id$
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #include "postgres.h"
15 
16 #include <sys/stat.h>
17 #include <unistd.h>
18 
19 #include "miscadmin.h"
20 #include "utils/guc.h"
21 #include "utils/rel.h"
22 
23 #include "citus_version.h"
24 #include "columnar/columnar.h"
25 
26 /* Default values for option parameters */
27 #define DEFAULT_STRIPE_ROW_COUNT 150000
28 #define DEFAULT_CHUNK_ROW_COUNT 10000
29 
30 #if HAVE_LIBZSTD
31 #define DEFAULT_COMPRESSION_TYPE COMPRESSION_ZSTD
32 #elif HAVE_LIBLZ4
33 #define DEFAULT_COMPRESSION_TYPE COMPRESSION_LZ4
34 #else
35 #define DEFAULT_COMPRESSION_TYPE COMPRESSION_PG_LZ
36 #endif
37 
38 int columnar_compression = DEFAULT_COMPRESSION_TYPE;
39 int columnar_stripe_row_limit = DEFAULT_STRIPE_ROW_COUNT;
40 int columnar_chunk_group_row_limit = DEFAULT_CHUNK_ROW_COUNT;
41 int columnar_compression_level = 3;
42 
43 static const struct config_enum_entry columnar_compression_options[] =
44 {
45 	{ "none", COMPRESSION_NONE, false },
46 	{ "pglz", COMPRESSION_PG_LZ, false },
47 #if HAVE_LIBLZ4
48 	{ "lz4", COMPRESSION_LZ4, false },
49 #endif
50 #if HAVE_LIBZSTD
51 	{ "zstd", COMPRESSION_ZSTD, false },
52 #endif
53 	{ NULL, 0, false }
54 };
55 
56 void
columnar_init_gucs()57 columnar_init_gucs()
58 {
59 	DefineCustomEnumVariable("columnar.compression",
60 							 "Compression type for columnar.",
61 							 NULL,
62 							 &columnar_compression,
63 							 DEFAULT_COMPRESSION_TYPE,
64 							 columnar_compression_options,
65 							 PGC_USERSET,
66 							 0,
67 							 NULL,
68 							 NULL,
69 							 NULL);
70 
71 	DefineCustomIntVariable("columnar.compression_level",
72 							"Compression level to be used with zstd.",
73 							NULL,
74 							&columnar_compression_level,
75 							3,
76 							COMPRESSION_LEVEL_MIN,
77 							COMPRESSION_LEVEL_MAX,
78 							PGC_USERSET,
79 							0,
80 							NULL,
81 							NULL,
82 							NULL);
83 
84 	DefineCustomIntVariable("columnar.stripe_row_limit",
85 							"Maximum number of tuples per stripe.",
86 							NULL,
87 							&columnar_stripe_row_limit,
88 							DEFAULT_STRIPE_ROW_COUNT,
89 							STRIPE_ROW_COUNT_MINIMUM,
90 							STRIPE_ROW_COUNT_MAXIMUM,
91 							PGC_USERSET,
92 							0,
93 							NULL,
94 							NULL,
95 							NULL);
96 
97 	DefineCustomIntVariable("columnar.chunk_group_row_limit",
98 							"Maximum number of rows per chunk.",
99 							NULL,
100 							&columnar_chunk_group_row_limit,
101 							DEFAULT_CHUNK_ROW_COUNT,
102 							CHUNK_ROW_COUNT_MINIMUM,
103 							CHUNK_ROW_COUNT_MAXIMUM,
104 							PGC_USERSET,
105 							0,
106 							NULL,
107 							NULL,
108 							NULL);
109 }
110 
111 
112 /*
113  * ParseCompressionType converts a string to a compression type.
114  * For compression algorithms that are invalid or not compiled, it
115  * returns COMPRESSION_TYPE_INVALID.
116  */
117 CompressionType
ParseCompressionType(const char * compressionTypeString)118 ParseCompressionType(const char *compressionTypeString)
119 {
120 	Assert(compressionTypeString != NULL);
121 
122 	for (int compressionIndex = 0;
123 		 columnar_compression_options[compressionIndex].name != NULL;
124 		 compressionIndex++)
125 	{
126 		const char *compressionName = columnar_compression_options[compressionIndex].name;
127 		if (strncmp(compressionTypeString, compressionName, NAMEDATALEN) == 0)
128 		{
129 			return columnar_compression_options[compressionIndex].val;
130 		}
131 	}
132 
133 	return COMPRESSION_TYPE_INVALID;
134 }
135 
136 
137 /*
138  * CompressionTypeStr returns string representation of a compression type.
139  * For compression algorithms that are invalid or not compiled, it
140  * returns NULL.
141  */
142 const char *
CompressionTypeStr(CompressionType requestedType)143 CompressionTypeStr(CompressionType requestedType)
144 {
145 	for (int compressionIndex = 0;
146 		 columnar_compression_options[compressionIndex].name != NULL;
147 		 compressionIndex++)
148 	{
149 		CompressionType compressionType =
150 			columnar_compression_options[compressionIndex].val;
151 		if (compressionType == requestedType)
152 		{
153 			return columnar_compression_options[compressionIndex].name;
154 		}
155 	}
156 
157 	return NULL;
158 }
159