07. Examples
1. Introduction
pldotnet is a programming language that allows you to write
Functions
, Procedures
, and DO
blocks in PostgreSQL using
either C# or F#. In this section, we will look at how to use
different types of arguments and return values in all the types of
structures blocks.
All function examples will have the SQL code to create it and an
example of a SELECT
statement to run it, followed by the output.
On the other hand the procedure examples will have a CALL
instead
of a SELECT
. All DO
Block examples will have only the DO
Block and the output.
You can find tests for all types of structures and for both plcsharp
and plfsharp
languages in the tests
folder.
2. Functions
To create a PostgreSQL function, you can use the CREATE FUNCTION
command. If a function with the same name already exists, you can
use CREATE OR REPLACE FUNCTION
to replace it. The AS $$
and $$ LANGUAGE
keywords indicate the start and end of the function's
body, which is written in C# or F# depending on the specified
programming language. plcsharp
refers to C# and plfsharp
refers
to F#.
2.1 C#
This section includes examples of PostgreSQL functions written using
plcsharp
, the C# procedural language.
2.1.1 Basic type
CREATE OR REPLACE FUNCTION sum2Integer(a integer, b integer) RETURNS integer AS $$
if (a == null)
a = 0;
if (b == null)
b = 0;
return a+b;
$$ LANGUAGE plcsharp;
The SELECT
executing it:
SELECT sum2Integer(32770, 100);
The Output:
sum2integer
-------------
32870
(1 row)
2.1.2 Array
CREATE OR REPLACE FUNCTION sumIntegerArray(integers integer[]) RETURNS integer AS $$
Array flatten_integers = Array.CreateInstance(typeof(object), integers.Length);
ArrayHandler.FlatArray(integers, ref flatten_integers);
int integers_sum = 0;
for(int i = 0; i < flatten_integers.Length; i++)
{
if (flatten_integers.GetValue(i) == null)
continue;
integers_sum = integers_sum + (int)flatten_integers.GetValue(i);
}
return integers_sum;
$$ LANGUAGE plcsharp STRICT;
The SELECT
executing it:
SELECT sumIntegerArray(ARRAY[2047483647::integer, null::integer, 304325::integer, 4356::integer]);
The Output:
sumintegerarray
-----------------
2047792328
(1 row)
2.1.3 String
CREATE OR REPLACE FUNCTION concatenateText(a text, b text) RETURNS text AS $$
if (a == null)
a = "";
if (b == null)
b = "";
string c = a + " " + b;
return c;
$$
LANGUAGE plcsharp;
The SELECT
executing it:
SELECT concatenateText('red', 'blue');
The Output:
concatenatetext
-----------------
red blue
(1 row)
2.1.4 Struct types
CREATE OR REPLACE FUNCTION modifyNetMask(my_inet INET, n INT) RETURNS INET AS
$$
return (my_inet.Address, my_inet.Netmask + n);
$$
LANGUAGE plcsharp STRICT;
The SELECT
executing it:
SELECT modifyNetMask(INET '192.168.0.1/24', 6);
The Output:
modifynetmask
----------------
192.168.0.1/30
(1 row)
2.2 F#
This section contains some PostgreSQL functions written in plfsharp
,
the F# procedural language.
2.2.1 Basic type
CREATE OR REPLACE FUNCTION distanceBetweenPointsFSharp(pointa point, pointb point) RETURNS float8 AS $$
let pointa = if pointa.HasValue then pointa.Value else NpgsqlPoint(0.0, 0.0)
let pointb = if pointb.HasValue then pointb.Value else NpgsqlPoint(0.0, 0.0)
let dif_x = pointa.X - pointb.X
let dif_y = pointa.Y - pointb.Y
let distance = Math.Sqrt(dif_x * dif_x + dif_y * dif_y)
distance
$$ LANGUAGE plfsharp;
The SELECT
executing it:
SELECT distanceBetweenPointsFSharp(POINT(1.5,2.75), POINT(3.0,4.75));
The Output:
distancebetweenpointsfsharp
-----------------------------
2.5
(1 row)
2.2.2 Array
CREATE OR REPLACE FUNCTION increaseCircleFSharp(orig_value CIRCLE) RETURNS CIRCLE AS $$
let orig_value = if orig_value.HasValue then orig_value.Value else NpgsqlCircle(NpgsqlPoint(0, 0), 3)
NpgsqlCircle(orig_value.Center, (orig_value.Radius + 1.0))
$$ LANGUAGE plfsharp;
The SELECT
executing it:
SELECT increaseCircleFSharp(NULL::CIRCLE);
The Output:
increasecirclefsharp
----------------------
<(0,0),4>
(1 row)
2.2.3 String
CREATE OR REPLACE FUNCTION modifyXmlFSharp(a XML) RETURNS XML AS $$
let mutable new_xml: string = ""
if System.Object.ReferenceEquals(a, null) ||a.Equals("") then
new_xml <- "<?xml version=\"1.0\" encoding=\"utf-8\"?><title>Hello, World, it was null!</title>"
else
new_xml <- a
new_xml <- (new_xml.Replace("Hello", "Goodbye")).Replace("World", "beautiful World")
new_xml
$$ LANGUAGE plfsharp;
The SELECT
executing it:
SELECT modifyXmlFSharp('<?xml version="1.0" encoding="utf-8"?><title>Hello, World!</title>'::XML)::text;
The Output:
modifyxmlfsharp
--------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?><title>Goodbye, beautiful World!</title>
(1 row)
2.2.4 Struct type
CREATE OR REPLACE FUNCTION modifyIPFSharp(my_inet INET, n INT) RETURNS INET AS $$
let struct (address, netmask) = if my_inet.HasValue then my_inet.Value else (IPAddress.Parse("127.0.0.1"), 21)
let bytes = address.GetAddressBytes()
let size = bytes.Length
bytes[size-1] <- bytes[size-1] + byte n.Value
struct (IPAddress(bytes), netmask)
$$ LANGUAGE plfsharp;
The SELECT
executing it:
SELECT modifyIPFSharp(INET '2001:db8:3333:4444:5555:6666:1.2.3.4/25', 20);
The Output:
modifyipfsharp
-----------------------------------------
2001:db8:3333:4444:5555:6666:102:318/25
(1 row)
3. Procedures
To create a PostgreSQL procedure, you can use the CREATE PROCEDURE
command. If a procedure with the same name already exists, you can
use CREATE OR REPLACE PROCEDURE
to replace it. The AS $$
and
$$ LANGUAGE
keywords mark the beginning and end of the procedure's
body, which is written in either C# (plcsharp
) or F# (plfsharp
),
depending on the specified programming language.
3.1 C#
This section includes examples of PostgreSQL procedures written
using plcsharp
, the C# procedural language.
3.1.1 Basic type
CREATE OR REPLACE PROCEDURE printSumProcedure(a integer, b integer) AS $$
int c = (int)a + (int)b;
Elog.Info($"c = {c}");
$$ LANGUAGE plcsharp;
The CALL
statements executing it:
CALL printSumProcedure(10, 25);
CALL printSumProcedure(1450, 275);
The Output:
INFO: c = 35
CALL
INFO: c = 1725
CALL
3.1.2 Array
CREATE OR REPLACE PROCEDURE printSmallestValueProcedure(doublevalues double precision[]) AS $$
double min = double.MaxValue;
for(int i = 0; i < doublevalues.Length; i++)
{
double value = (double)doublevalues.GetValue(i);
min = min < value ? min : value;
}
Elog.Info($"Minimum value = {min}");
$$ LANGUAGE plcsharp;
The CALL
statements executing it:
CALL printSmallestValueProcedure(ARRAY[2.25698, 2.85956, 2.85456, 0.00128, 0.00127, 2.36875]);
CALL printSmallestValueProcedure(ARRAY[2.25698, -2.85956, 2.85456, -0.00128, 0.00127, 12.36875, -23.2354]);
The Output:
INFO: Minimum value = 0.00127
CALL
INFO: Minimum value = -23.2354
CALL
3.2 F#
This section contains examples of PostgreSQL procedures written
using plfsharp
, the F# procedural language.
3.2.1 Basic type
CREATE OR REPLACE PROCEDURE printSumProcedureFSharp(a integer, b integer) AS $$
let c = a.Value + b.Value
Elog.Info("[F#] c = " + c.ToString())
$$ LANGUAGE plfsharp;
The CALL
statements executing it:
CALL printSumProcedureFSharp(10, 25);
CALL printSumProcedureFSharp(1450, 275);
The Output:
INFO: [F#] c = 35
CALL
INFO: [F#] c = 1725
CALL
3.2.2 String
CREATE OR REPLACE PROCEDURE sayHelloFSharp(name TEXT) AS $$
let message = "Hello, " + name + "! Welcome to plfsharp."
Elog.Info(message)
$$ LANGUAGE plfsharp;
The CALL
statements executing it:
CALL sayHelloFSharp('Mikael'::TEXT);
CALL sayHelloFSharp('Rosicley'::TEXT);
CALL sayHelloFSharp('Todd'::TEXT);
The Output:
INFO: Hello, Mikael! Welcome to plfsharp.
CALL
INFO: Hello, Rosicley! Welcome to plfsharp.
CALL
INFO: Hello, Todd! Welcome to plfsharp.
CALL
4. DO
blocks
DO
Blocks
are temporary scripts that are executed and then discarded.
To create a DO
block, use the DO $$
and $$ LANGUAGE
keywords
to define the beginning and end of the block's body, which is written
in either C# (plcsharp
) or F# (plfsharp
).
4.1 C#
This section includes examples of PostgreSQL DO
blocks written
using plcsharp
, the C# procedural language.
4.1.1 Basic type
DO $$
int c = 1450 + 275;
Elog.Info($"c = {c}");
$$
language plcsharp;
The output:
INFO: c = 1725
DO
4.1.2 Array
do $$
double[] doublevalues = {2.25698, 2.85956, 2.85456, 0.00128, 0.00127, 2.36875};
double min = double.MaxValue;
for(int i = 0; i < doublevalues.Length; i++)
{
double value = (double)doublevalues.GetValue(i);
min = min < value ? min : value;
}
Elog.Info($"Minimum value = {min}");
$$ language plcsharp;
The output:
INFO: Minimum value = 0.00127
DO
4.2 F#
This section includes examples of PostgreSQL DO
blocks written
using plfsharp
, the F# procedural language.
4.2.1 Basic type
DO $$
let c = 1450 + 275
Elog.Info("c = " + c.ToString())
$$ language plfsharp;
The output:
INFO: c = 1725
DO
4.2.2 String
DO $$
let message = "PL.NET IS THE BEST PROCEDURE LANGUAGE!"
Elog.Info(message)
$$
language plfsharp;
The output:
INFO: PL.NET IS THE BEST PROCEDURE LANGUAGE!
DO