nyuuzyou/wikis huggingface dataset:
Count nulls

Author: Alvaro Herrera, sponsored by Enova Financial
Comment by: Alexey Klyukin
This is a simple function that counts a number of NULLs among its arguments.
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
Datum count_nulls(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(count_nulls);
Datum
count_nulls(PG_FUNCTION_ARGS)
{
	int		nargs = PG_NARGS();
	int		num_nulls = 0;
	int		i;
	for (i = 0; i < nargs; i++)
	{
		if (PG_ARGISNULL(i))
			num_nulls++;
	}
	PG_RETURN_INT32(num_nulls);
}
The relevant SQL definition (for 8.4 and above):
create or replace function countnulls(VARIADIC "any") returns int language 'c' IMMUTABLE as 'countnulls', 'count_nulls';
If you are on 8.3 and below you have to declare each N-argument function separately due to a lack of VARIADIC:
create function countnulls("any") returns int language 'c' IMMUTABLE as 'countnulls', 'count_nulls';
create function countnulls("any", "any") returns int language 'c' IMMUTABLE as 'countnulls', 'count_nulls';	
create function countnulls("any", "any", "any") returns int language 'c' IMMUTABLE as 'countnulls', 'count_nulls';
create function countnulls("any", "any", "any", "any") returns int language 'c' IMMUTABLE as 'countnulls', 'count_nulls';
create function countnulls("any", "any", "any", "any", "any") returns int language 'c' IMMUTABLE as 'countnulls', 'count_nulls';
create function countnulls("any", "any", "any", "any", "any", "any") returns int language 'c' IMMUTABLE as 'countnulls', 'count_nulls';
create function countnulls("any", "any", "any", "any", "any", "any", "any") returns int language 'c' IMMUTABLE as 'countnulls', 'count_nulls';
create function countnulls("any", "any", "any", "any", "any", "any", "any", "any") returns int language 'c' IMMUTABLE as 'countnulls', 'count_nulls';	
One should build it with a fairly standard Makefile:
MODULE_big = countnulls
OBJS = count_nulls.o
DATA = countnulls.sql
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
A simple usage example, let's install a constraint on a table that would check that exactly one table column is NULL in every row.
# CREATE TABLE foo(bar int, baz text, check(countnulls(bar,baz) = 1));
CREATE TABLE
# INSERT INTO foo VALUES(1,2);
ERROR: new row for relation "foo" violates check constraint "foo_check"
# INSERT INTO foo VALUES(NULL, NULL);
ERROR: new row for relation "foo" violates check constraint "foo_check"
# INSERT INTO foo VALUES(NULL, 1);
INSERT 0 1
CPF

CPF validation implemented by Euler Taveira de Oliveira
in pure SQL.
--
-- Esta função retorna true se o CPF é válido e falso caso contrário
-- Ela verifica o tamanho e os dígitos verificadores
--
CREATE OR REPLACE FUNCTION verify_cpf(text)
RETURNS BOOLEAN AS $$
-- se o tamanho for 11 prossiga com o cálculo
-- senão retorne falso
SELECT CASE WHEN length($1) = 11 THEN
(
 -- verifica se os dígitos coincidem com os especificados
 SELECT
 substr($1, 10, 1) = CAST(digit1 AS text) AND
 substr($1, 11, 1) = CAST(digit2 AS text)
 FROM
 (
 -- calcula o segundo dígito verificador (digit2)
 SELECT
 -- se o resultado do módulo for 0 ou 1 temos 0
 -- senão temos a subtração de 11 pelo resultado do módulo
 CASE res2
 WHEN 0 THEN 0
 WHEN 1 THEN 0
 ELSE 11 - res2
 END AS digit2,
 digit1
 FROM
 (
 -- soma da multiplicação dos primeiros 9 dígitos por 11, 10, ..., 4, 3
 -- obtemos o módulo da soma por 11
 SELECT
 MOD(SUM(m * CAST(substr($1, 12 - m, 1) AS integer)) + digit1 * 2, 11) AS res2,
 digit1
 FROM
 generate_series(11, 3, -1) AS m,
 (
 -- calcula o primeiro dígito verificador (digit1)
 SELECT
 -- se o resultado do módulo for 0 ou 1 temos 0
 -- senão temos a subtração de 11 pelo resultado do módulo
 CASE res1
 WHEN 0 THEN 0
 WHEN 1 THEN 0
 ELSE 11 - res1
 END AS digit1
 FROM
 (
 -- soma da multiplicação dos primeiros 9 dígitos por 10, 9, ..., 3, 2
 -- obtemos o módulo da soma por 11
 SELECT
 MOD(SUM(n * CAST(substr($1, 11 - n, 1) AS integer)), 11) AS res1
 FROM generate_series(10, 2, -1) AS n
 ) AS sum1
 ) AS first_digit
 GROUP BY digit1
 ) AS sum2
 ) AS first_sec_digit
)
ELSE false END;
$$ LANGUAGE 'SQL'
IMMUTABLE STRICT;
COMMENT ON FUNCTION verify_cpf(text) IS 'retorna verdadeiro se e, somente se, o CPF 
possui o tamanho correto (11 dígitos) e os dígitos calculados coincidem com os especificados';
Category:SQL
Category:Português
Creando Hash en tablas para mejorar rendimiento

=== Creando hash en tabla para mejorar rendimiento ===
ARTICULO AUN EN REVISIÓN Y PROCESO DE DEPURACIÓN.
Este artículo implementa una técnica poco convencional para mejorar la performance
de las querys creando un hash de los campos de texto de nuestras tablas. Esto
sirve para busquedas exactas, si lo que quieren es busqueda de palabras deberán leer
un poco más de TSearch (incluido en Pgsql84).
== Utilizando CRC32 ==
Creamos un archivo llamado crc.c y guardamos el siguiente código en el archivo:
/*
 * CYCLIC REDUNDANCY CHECK
 */
#include "postgres.h"
#include "fmgr.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(pg_crc_simple);
Datum 
pg_crc_simple(PG_FUNCTION_ARGS){
 char *message = PG_GETARG_TEXT_P(0);
 //size_t argumentlen = VARSIZE(message)-VARHDRSZ;
 int i, j;
 unsigned int byte, crc, mask;
 int32 normalize;
 static unsigned int table[256];
 /* Seteamos la tabla de ser necesario. */
 if (table[1] == 0) {
 for (byte = 0; byte <= 255; byte++) {
 crc = byte;
 for (j = 7; j >= 0; j--) { // 8veces
 mask = -(crc & 1);
 crc = (crc >> 1) ^ (0xEDB88320 & mask);
 }
 table[byte] = crc;
 }
 }
 /* tenemos la tabla y calculamos*/
 i = 0;
 crc = 0xFFFFFFFF;
 while (message[i] != 0) {
 byte = message[i]; // Get next byte.
 crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF];
 i = i + 1;
 }
 
 normalize = -(~crc);
 PG_RETURN_INT32(normalize);
}
Luego lo compilamos como un shared object:
gcc -I $DIRECTORIO_POSTGRES/include/server/ --shared crc.c
Luego, tenemos que incluir esa función en el motor:
CREATE OR REPLACE FUNCTION pg_crc_simple(text) RETURNS integer
 AS '/usr/local/pgsql84/a.out', 'pg_crc_simple'
 LANGUAGE C STRICT;
Notese que compile el código en la carpeta /usr/local/pgsql84 y por defecto el 'gcc' nombra al archivo de salida como a.out.
Probemos como funciona!
postgres=# select pg_crc_simple(random()::text);
 pg_crc_simple_2 
-----------------
 1107002784
(1 row)
== Aplicación sobre la tabla ==
Suponemos entonces tenemos una tabla con el campo que queremos hashear y el campo donde guardaremos ese valor.
create table miTablita(nombre text,nombreCrc int);
Ahora inserto los nombres y luego sus CRC:
insert into miTablita(nombre) (select substring(random()::text,3,9) from generate_series(1,100) );
update miTablita set nombreCrc = pg_crc_simple_2(nombre);
Category:Español
CREATE COLLATION

===== 名字 =====
CREATE COLLATION -- 定义一个新的字符序
===== 语法概要 =====
 CREATE COLLATION name (
 [ LOCALE = locale, ]
 [ LC_COLLATE = lc_collate, ]
 [ LC_CTYPE = lc_ctype ]
 )
 CREATE COLLATION name FROM existing_collation
===== 描述 =====
CREATE COLLATION 命令利用操作系统的特定区域信息定义一个新的字符序，或者通过拷贝一个现有的定义。
为了创建字符序，你必须在目标模式上具有 CREATE 权限。
===== 参数 =====
;name
:字符序的名字，可以使用模式进行修饰。如果没有用模式修饰，那么就在当前模式中定义。一个模式中的字符序名字必须唯一。（系统编目中可以存在同名但不同编码的字符序，但是如果数据库编码不匹配的话这些字符序会被忽略）
;locale
:同事设置LC_COLLATE和LC_CTYPE的快捷方式。如果使用这个参数，就不能再使用LC_COLLATE或LC_CTYPE参数。
;lc_collate
:使用操作系统特定区域的LC_COLLATE信息。区域必须能适用于当前数据库编码。（详细的规则请参见 CREATE DATABASE命令）
;lc_ctype
:使用操作系统特定区域的LC_CTYPE信息。区域必须能适用于当前数据库编码。（详细的规则请参见 CREATE DATABASE命令）
;existing_collation
:拷贝的现有字符序名字。新定义的字符序和被拷贝的字符序具有相同的属性，但它们是独立的对象。
===== 注意 =====
使用 DROP COLLATION 命令删除一个用户自定义字符序。
PostgreSQL对字符序的支持可以参见第 22.2 章。
===== 示例 =====
从操作系统区域 fr_FR.utf8 创建一个字符序（假定当前数据库编码为UTF8）：
 CREATE COLLATION french (LOCALE = 'fr_FR.utf8');
从现有字符序创建一个字符序：
 CREATE COLLATION german FROM "de_DE";
如果可以在应用中使用操作系统无关的字符序的话，往往会带来方便的效果。
===== 兼容性 =====
SQL 标准只有从现有字符序拷贝的操作。新建字符序的操作属于PostgreSQL的扩展。
===== 参见=====
ALTER COLLATION, DROP COLLATION
Create INSERT statement

Sometimes you might want to create an INSERT statement which reproduces a particular row in a table. It's simple enough to do with the help of a PL/PgSQL function:
CREATE OR REPLACE FUNCTION create_insert_statement(regclass, anyelement) RETURNS text
 LANGUAGE plpgsql
 AS $$
DECLARE
_schemaname text;
_tablename text;
_key text;
_value text;
_columns text[];
_values text[];
BEGIN
SELECT pg_namespace.nspname, pg_class.relname
INTO STRICT _schemaname, _tablename
FROM pg_class
JOIN pg_namespace
 ON (pg_namespace.oid = pg_class.relnamespace)
WHERE pg_class.oid = $1;
FOR _key IN
 SELECT columns.column_name
 FROM information_schema.columns
 WHERE columns.table_schema = _schemaname
 AND columns.table_name = _tablename
 ORDER BY columns.ordinal_position
LOOP
 EXECUTE format($s$SELECT format('%%L', ((($1)::%s).%I))$s$, $1, _key) USING $2 INTO STRICT _value;
 _columns := _columns || _key;
 _values := _values || _value;
END LOOP;
RETURN format('INSERT INTO %s (%s) VALUES (%s)', $1, array_to_string(_columns, ','), array_to_string(_values, ','));
END;
$$;
Then you can call the function like this:
CREATE TABLE mytable(a int, b int);
INSERT INTO mytable VALUES (0, -999);
SELECT create_insert_statement(tableoid, mytable) FROM mytable;
-- returns
-- create_insert_statement 
-------------------------------------------------
-- INSERT INTO mytable (a,b) VALUES ('0','-999')
--(1 row)
Category:PL/pgSQL
CREATE OR REPLACE LANGUAGE

== For PostgreSQL 9.0 and newer ==
In current releases of PostgreSQL "CREATE OR REPLACE LANGUAGE" is the native syntax for installing a procedural language with no error if it's already installed.
Also PL/pgSQL is installed in the template databases at install time, so will be included in all newly created databases by default, so there's usually no need to install it in schema installation scripts.
== For PostgreSQL 8.4 and older ==
While there is no CREATE OR REPLACE for languages like there are for functions, you can simulate one for the common case where you want to add the pl/pgsql language to a database. Normally this will trigger an ERROR condition if the language is already installed:
$ psql -c "CREATE LANGUAGE plpgsql"
ERROR: language "plpgsql" already exists
But the following snippet will add the language only if it doesn't already exist:
CREATE OR REPLACE FUNCTION make_plpgsql()
RETURNS VOID
LANGUAGE SQL
AS $$
CREATE LANGUAGE plpgsql;
$$;
SELECT
 CASE
 WHEN EXISTS(
 SELECT 1
 FROM pg_catalog.pg_language
 WHERE lanname='plpgsql'
 )
 THEN NULL
 ELSE make_plpgsql() END;
DROP FUNCTION make_plpgsql();
You can run this multiple times and it will never produce the error shown above. The DROP FUNCTION at the end is optional, if you want to re-use this snippet in other code you might keep the function around to be referenced later.
* Original code by David Fetter
CREATE PRIVATE VARIABLE

==Introduction==
One of missed functionality related to stored procedures is possibility to work with "unit" private variables. The following proposal describe introduction a schema private variables.
Now, we use a schemas for PL code modularization. The introduction of schema private variables is natural. The variables are:
* accessible from schema related objects - functions (or views in future),
* initialized when session is started (when default is not null), and destroyed when session is finishing,
* accessed via get/set functions from all PL functions,
* accessed via schema qualified identifier in PL/pgSQL. The schema identification should or should not be required. This can be controlled by PL/pgSQL option,
* stored binary in PostgreSQL native format.
CREATE PRIVATE VARIABLE my_schema.login_time timestamp DEFAULT current_timestamp;
CREATE PRIVATE VARIABLE my_schema.session_state state_type DEFAULT init_state();
CREATE PRIVATE VARIABLE my_schema.counter2 int; -- the NULL is default
This proposal doesn't introduce "public" variables, although these variables can be introduced later. But my opinion about public variables is negative. 
==Some examples==
CREATE OR REPLACE FUNCTION init_state(OUT state state_type)
AS $$
BEGIN
 state.user := current_user;
 state.counter := 0;
 RETURN;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION my_schema.increase_counter()
RETURNS int AS $$
BEGIN
 -- by default qualified name is required
 -- using "counter" only raises a error
 my_schema.counter := my_schema.counter + 1;
 RETURN my_schema.counter;
END;
$$ LANGUAGE plpgsql;
-- better, doesn't need on_connect initialization
CREATE OR REPLACE FUNCTION my_schema.increase_counter2()
RETURNS int AS $$
BEGIN
 my_schema.counter2 := COALESCE(my_schema.counter2 + 1, 1);
 RETURN my_schema.counter2;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION my_schema.increase_counter_python()
RETURNS int AS $$
 result = plpy.get_private_var("counter) + 1
 plpy.set_private_var("counter", result)
 return result
$$ LANGUAGE plpythonu;
-- but when function is not in "my_schema", same code can fail
CREATE OR REPLACE FUNCTION public.increase_counter_python_fail()
RETURNS int AS $$
 result = plpy.get_private_var("counter") + 1 # runtime error "schema private variable not found"
 plpy.set_private_var("counter", result)
 return result
$$ LANGUAGE plpythonu;
-- this doesn't work too
CREATE OR REPLACE FUNCTION my_schema.foo()
RETURNS int AS $$
BEGIN
 RETURN public.increase_counter_python_fail();
END;
$$ LANGUAGE plpgsql;
-- but following code should to work
-- user have to have a rights for running my_schema.increase_counter_python
CREATE OR REPLACE FUNCTION public.foo()
RETURNS int AS $$
BEGIN
 RETURN my_schema.increase_counter_python();
END;
$$ LANGUAGE plpgsql;
CTE Bounties

To encourage the creative use of CTE expressions, here is a list of problems. Be the first to solve one and get your name listed!
* Euler Project, Question 1
* Topographical Sort
* Insertion Sort
* Quicksort
* Fibonacci Numbers
* Sieve of Eratosthenes
* Sudoku solver
Please link the solution page into the snippets category as well.
Category:WITH Queries
Culturally aware initcap

Written by Peter Geoghegan ("sternocera")
The following is an implementation of what I call "culturally aware initcap", which is usable as a drop-in replacement for initcap, provided input is in English. It solves a number of problems I've often encountered when using regular initcap, particularly with possessive apostrophes, but also with various common contractions (isn't, can't, won't, I'm, you've, you're). It does this without stepping on the toes of people with Irish names like O'Shaughnessy and O'Sullivan. 
with regular initcap: SELECT initcap($$O'SULLIVAN'S friend DOESN'T LIVE HERE anymore$$)
output: "O'Sullivan'S Friend Doesn'T Live Here Anymore"
with cul_initcap: SELECT cul_initcap($$O'SULLIVAN'S friend DOESN'T LIVE HERE anymore$$)
output: "O'Sullivan's Friend Doesn't Live Here Anymore"
CREATE OR REPLACE FUNCTION cul_initcap(input_val text) RETURNS text AS
$function_body$
 SELECT 
 replace(
 replace(
 replace(
 replace(
 replace(
 replace(
 replace(
 regexp_replace(initcap($1), 
 $$'(([MSTD]|Ve|Re|Ll))([^[:upper:][:lower:]]|$)$$, 
 $$'{@*#!\1!#*@}\3$$, 
 'g'
 )
 , '{@*#!M!#*@}', 'm')
 , '{@*#!S!#*@}', 's')
 , '{@*#!T!#*@}', 't')
 , '{@*#!D!#*@}', 'd')
 , '{@*#!Ve!#*@}', 've')
 , '{@*#!Re!#*@}', 're')
 , '{@*#!Ll!#*@}', 'll');
$function_body$
LANGUAGE 'sql' IMMUTABLE STRICT;
One notable limitation of my implementation is that it will incorrectly convert "magical brace enclosed literals" into their corresponding output values: '{@*#!T!#*@}' ,'{@*#!S!#*@}', '{@*#!M!#*@}', '{@*#!Ve!#*@}' (and the rest) become 't', 's', 'm' and 've' respectively. I doubt that this is much of a concern generally. If it is a concern, use more elaborate magical braces that are even less likely to occur in strings that exist in production.
Category:SQL
CustomCumulativeStats

= Custom Cumulative Statistics (pgstats) =
Extensions can register their own custom cumulative statistics to the gathering of any statistical data using the same APIs as PostgreSQL's backend pgstats.
Each custom cumulative statistics needs to register using a unique ID (across all extensions) to prevent problems with conflicts when handling the stats data (hash key in dshash table, read and write of pgstats file). The IDs are limited at compile-time, however, and only IDs between 128 and 255 (inclusive) are available natively for custom cumulative statistics as of PostgreSQL 18. It is possible to change this limit.
This page lists the current extensions that require custom cumulative stats, and the IDs which are reserved for them. If your extension requires a new type of custom cumulative statistics, start out by using PGSTAT_KIND_EXPERIMENTAL (128). When the project is close to release or being used in production, choose an unused stats kind ID and add to this list to reserve it.
End-users must ensure that the extensions they deploy do not conflict, while it's not expected with open source extensions for which authors must take care of the current list, close source extensions could easily overlap.
= List of Custom Stats =
KindId	Extension	Description 	License
128 	N/A 	Used for extensions still in development 	N/A
129 	N/A 	In-core test module injection_points, variable-numbered case	N/A
130 	N/A 	In-core test module injection_points, fixed-numbered case 	N/A
CustomExec

= Brief Idea =
The purpose of ExecNodeExtender allows extensions to replace a part of Plan node in PlannedStmt by the self defined node type, and run it as if built-in executor nodes. It enables a cutting-edge but not upstreamed feature to implement its own query execution instead of the standard one, without branching whole of the source code.
This idea tries to adds a new plan node type (ExtendExec) that is associated with several callback functions to be implemented in extension module. 
Existing planner_hook is a good strategic point to adjust the PlannedStmt being constructed by standard planner. Once an extension inject an ExtendExec node into the Plan tree underlying PlannedStmt, related callback shall be invoked on several points, therefore, extension can implement its own logic as a part of regular executor.
Also see the discussion in developer meeting 2013.
= API Specification =
TODO: add mode detailed description
== Data Structure ==
 typedef struct {
 const char *extender_name;
 ExecNodeExtender_BeginExec_function fn_begin_exec;
 ExecNodeExtender_GetNext_function fn_getnext;
 ExecNodeExtender_ReScan_function fn_rescan;
 ExecNodeExtender_EndExec_function fn_end_exec;
 ExecNodeExtender_Explain_function fn_explain;
 } ENExecRoutine;
 typedef struct {
 Plan plan;
 Index enexec_id;
 List *private_list;
 } ENExec;
 typedef strcut {
 PlanState ps;
 ENExecRoutine *routine;
 void *private;
 } ENExecState;
== Registration ==
 Index RegisterExecNodeExtender(const ENExecRoutine *routine);
It shall be usually called at shared_preload_libraries handler of extension,
to register a set of callback routines associated with the self-defined exec node.
It saves a pair of name and callbacks of self-defined exec node on an internal array, and returns its index.
== BeginExec ==
 void
 ExecNodeExtender_BeginExec(ENExecState *state, int eflags);
It shall be invoked at ExecInitNode(), to initialize ENExecState structure.
== GetNext ==
 TupleTableSlot *
 ExecNodeExtender_GetNext(ENExecState *state);
It shall be invoked at ExecProcNode(), to return a tuple as result of execution of underlying exec nodes.
== ReScan ==
 void
 ExecNodeExtender_ReScan(ENExecState *state);
It shall be invoked at ExecReScan(), to rewind this exec node.
== EndExec ==
 void
 ExecNodeExtender_EndExec(ENExecState *state);
It shall be invoked at ExecEndNode(), to finalize this exec node.
== Explain ==
 void
 ExecNodeExplain(ENExecState *state, ExplainState *es);
It shall be optionally invoked at ExplainNode(), to show explain text.
= Possible use case =
* SeqScsn assisted by GPU
* Sort/Aggregate assisted by GPU
* Scan with RangeVar qualifier
* Scan from cluster-wide relations
* Aggregate functions assisted by CPU SIMD operators (contrib module for PoC)
* ...and more?
CustomWALResourceManagers

= Custom WAL Resource Manager (rmgr) =
Extensions can register their own custom WAL resource managers to support custom redo, physical replication, and logical replication/decoding.
Each resource manager needs to register using a unique ID (across all extensions) to prevent problems with crash recovery and replication. The IDs are limited, however, and only IDs between 128 and 255 (inclusive) are available for custom resource managers.
This page lists the current extensions that require a custom resource manager, and the IDs which are reserved for them. If your extension requires a new custom resource manager, start out by using RM_EXPERIMENTAL_ID (128). When the project is close to release or being used in production, choose an unused resource manager ID and add to this list to reserve it.
End-users must ensure that the extensions they deploy do not conflict, while it's not expected with open source extensions for which authors must take care of the current list, close source extensions could easily overlap.
= List of Custom Rmgrs =
RmgrId	Extension 	Description 	License
128 	N/A 	Used for extensions still in development 	N/A
129 	OrioleDB 	OrioleDB – building a modern cloud-native storage engine (... and solving some PostgreSQL wicked problems) 🇺🇦	PostgreSQL License
130 	EnterpriseDB	Bluefin – Compressed IoT storage 	Proprietary
131 	EnterpriseDB	Bluefin2 – Compressed IoT storage 	Proprietary
132 	EnterpriseDB	Marlin – High Update storage 	Proprietary
133 	EnterpriseDB	Marlin2 – High Update storage 	Proprietary
134 	Neon 	Neon storage system 	Apache 2
135 	PostgresPro 	AQO – Adaptive query optimization 	Proprietary
136 	PostgresPro 	sr_plan – Save and restore plan 	Proprietary
137 	pg_analytics	pg_analytics extension 	GNU AGPL3
138 	PGroonga 	PGroonga - Fast full text search index for all languages 	PostgreSQL License
139 	EnterpriseDB	Hsphere - Hypersphere AI embedding index 	Proprietary
140 	Percona 	pg_tde - data at rest encryption extension 	MIT
241 	Columnar 	Columnar compression extension 	GNU AGPL3
Category:Extensions