-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* up to date (#1) * Cleanup * Use latest version of docker * Remove Docker first * Remove more of Docker * Start Docker after installing * fixed misspecification * breaking apart the workshop * beginning * finished first page and added to the dir * more scaffolding * more progress * mid progress in page 3 * a little more * done for now * fixing commands * normal typo and bug finding * typo fixes from @davecramer * more general cleanup * trying to see pgadmin4 * missing hyphens matter * trying later version of pgadmin * roll that back * think I got it * think I got it * Modified property to show correctly the tabs (#3) Signed-off-by: Gabriela S. Soria <[email protected]> * some bug fixes and new module * fixing image * fixing image * Fixing functions * Beginnings of pgadmin class * getting the DBA stuff in
- Loading branch information
Showing
19 changed files
with
688 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Connecting to our Database | ||
|
||
If you look at the second tab in our learning interface it says PgAdmin4. Go ahead and click that tab which should spawn a new browser window or tab. You may have to wait a few seconds while the PGAdmin4 interface gets rendered. You should now be able | ||
to login using username _admin_ and password _password_. | ||
|
||
## First screen | ||
|
||
You should be seeing a screen that looks like this: | ||
|
||
![Home Screen](basicpgadmin/assets/01-home-screen.png) | ||
|
||
This is the home page for PgAdmin4. Before we can do anything meaningful we need to connect to a PostgreSQL server. There are two ways to do this: | ||
|
||
1. Click on the "Add New Server" butting in the middle of the screen. | ||
1. Right click on the Servers icon in the top left of the left navigation panel. | ||
|
||
Let's start by doing the right click option because it will give us more flexibility. | ||
|
||
### Right click options | ||
|
||
![Create Server](basicpgadmin/assets/01-server-selection.png) | ||
|
||
When you right click on the icon you should see a list of options. Go ahead and mouse over _create_. This will then show _server group_ and _server_. If you are going to manage and interact with a lot of PostgreSQL servers then you might want to create server groups such as testing vs production. Server groups is just a logical organization in the PgAdmin interface. | ||
|
||
|
||
|
||
In our case since we are only managing one server, go ahead and click server to bring up the new create server dialog. | ||
|
||
## Create Server Dialog | ||
|
||
While there are quite a few boxes and tabs in this dialog, only a few of them are actually required to create a new server in PgAdmin. | ||
|
||
### First Tab | ||
|
||
![First Tab](basicpgadmin/assets/01-create-server-tab1.png) | ||
|
||
On the general tab, the only field required is _Name_. This name represents the name YOU want to use to identify this PostgreSQL server in the PgAdmin interface. You could call it monkey if you want - it doesn't **require** any relation to a name in the real world. | ||
|
||
For today's exercise let's name it "Workshop" | ||
|
||
In the comment field you can put in some information about this server connection. The information can be brought up in the interface later and can help you remember facts about this server. | ||
|
||
Once you are done filling in those fields go ahead and click on the second tab titled _Connection_. | ||
|
||
### Second Tab | ||
|
||
This _Connection_ tab contains most of the important information about your server. | ||
|
||
![Second Tab](basicpgadmin/assets/01-create-server-tab2.png) | ||
|
||
|
||
## Wrap Up | ||
We just finished the basic skeleton of a function: declaration, function name, parameters, return type, code block, and | ||
language used. In our next exercise we will explore doing more with the function declaration and parameters. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
# Function Declarations and Parameters | ||
|
||
While our function is amazing, perhaps we do want to do a bit of editing to it. Maybe accept some parameters or change | ||
the code. | ||
|
||
## Create versus Replace | ||
|
||
Functions are immutable, there is no way to edit them in place. So while we used CREATE in our first example, the | ||
recommended pattern is to instead say "CREATE or REPLACE FUNCTION" | ||
|
||
This tells PostgreSQL if this function doesn't exist then create it otherwise, replace the one that is there. From now on | ||
we are going to use this so we can keep iterating on our function. | ||
|
||
## Parameterising Our Function | ||
|
||
You know the next step in our function right? Of course we need to get it so say "Hello [your name]". Let's start with the | ||
simplest way possible | ||
|
||
``` | ||
CREATE OR REPLACE FUNCTION brilliance(varchar) | ||
RETURNS VARCHAR AS | ||
```{{execute}} | ||
We are saying that this function requires the caller to pass in a string along with the function call. From the PostgreSQL | ||
documentation: | ||
The argument types can be base, composite, or domain types, or can reference the type of a table column. | ||
Just use the type as if you were defining a column in a table. | ||
### Referencing the Parameter in the Code | ||
Now we can use this parameter in the code. | ||
``` | ||
$$ | ||
SELECT 'hello ' || $1; | ||
$$ | ||
LANGUAGE sql; | ||
```{{execute}} | ||
If we had used more parameters we would keep incrementing the $number for each new parameter. The '||' is the concatenation | ||
operator per the SQL standard. | ||
Let's go ahead and use our cool new function! | ||
``` | ||
select brilliance('student'); | ||
```{{execute}} | ||
Go ahead and change the name to anything else you want to try. | ||
## Better Parameter Names | ||
While it was easy to just put in 'varchar' for the parameter, that is not as easy to use and read in the body of our code. | ||
Let's clean this up and make more literate code. You can give a name to the parameter and it appears right before the type | ||
declaration. We will also add another parameter so you can see how to handle passing in multiple named variables. | ||
``` | ||
CREATE OR REPLACE FUNCTION brilliance(name varchar, rank int) | ||
RETURNS VARCHAR AS | ||
$$ | ||
SELECT 'hello ' || name || '! You are number ' || rank; | ||
$$ | ||
LANGUAGE sql; | ||
```{{execute}} | ||
This code is much more readable and maintainable. We also got to see that the '||' operator will work with non-string types | ||
as long as there is one string type in the concatenation. | ||
Time to exercise our function again: | ||
``` | ||
select brilliance('student', 1); | ||
```{{execute}} | ||
## Default Values for Parameters | ||
It is also possible to specify default values for parameters for when the function is called without a value for a parameter. | ||
**Note**, if you have a list of parameters, once you specify a default value for a parameter ALL following parameters must | ||
have default values as well. | ||
Let's go ahead and specify default values for both parameters in our great new function. | ||
``` | ||
CREATE OR REPLACE FUNCTION brilliance(name varchar = 'Jorge', rank int = 7) | ||
RETURNS VARCHAR AS | ||
$$ | ||
SELECT 'hello ' || name || '! You are number ' || rank; | ||
$$ | ||
LANGUAGE sql; | ||
```{{execute}} | ||
And now if we call our function we will get those values if we don't specify a value. Before we do this we need to drop our | ||
original function - think about why?.... | ||
``` | ||
DROP FUNCTION brilliance(); | ||
``` | ||
Since we already wrote a function named brilliance in step 1 that accepted no parameters, it is going to try and use that | ||
rather than what we want to happen here. | ||
``` | ||
select brilliance(); | ||
```{{execute}} | ||
But we can also specify only one parameter and use the parameter name. Read more in the [official docs](https://www.postgresql.org/docs/11/sql-syntax-calling-funcs.html) about how | ||
to call functions: | ||
``` | ||
select brilliance(rank => 1); | ||
```{{execute}} | ||
## Wrap Up | ||
**NOTE** No two functions can have the same name UNLESS they have different parameter signatures. | ||
For example, you can't have two functions named _myfunction_ unless one is myfunction() | ||
and the other is myfunction(myparam varchar). You could actually have functions: | ||
1. myfunction() | ||
1. myfunction(varchar) | ||
1. myfunction(int) | ||
As long as the parameters are different (order does not matter) they can co-exist. What this also means is that you can | ||
overload a function to do different behavior depending on the types passed in.As we saw above, having default values | ||
along with over-ridden function names can sometimes cause issues for the users of the functions. | ||
Keep this in mind if you run into an error or trying to determine how to architect your functions. | ||
Though we covered the basics of adding parameters to your functions we will return to this as we move on to the next section. | ||
In the next exercise we will cover different ways to return values and how to handle different return types. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
# Return Types | ||
|
||
For this final section we are going to cover all the ways you can return data from your functions as well how to handle | ||
different data return types. Let's move on from just returning a single value and perhaps throw in a little Pl/PGSQL the | ||
procedural language included with PostgreSQL. | ||
|
||
We will start by showing how the actual RETURN statement is not necessary. | ||
|
||
## IN, OUT, and INOUT Paremeters | ||
|
||
PostgreSQL allows you to specify the "direction" data flows into a function based on how you declare the parameter. By | ||
default all parameters are specified as IN parameters, meaning data is only passed into the function with the parameter. | ||
|
||
If you declare a parameter as OUT then data will be returned. You can have more than one OUT parameter in a function. Using a | ||
RETURNS {type} AS statement when you have OUT parameters is optional. If you | ||
use the RETURNS {type}AS statement with your function, it's type must match the type of our OUT parameters. | ||
|
||
An INOUT parameter means it will be used to pass data in and then return data through this parameter name as well | ||
|
||
For our function let's get rid of the RETURNS {type} AS statement and add another OUT parameter. We have to drop our function first | ||
because Postgresql does NOT consider OUT parameters as a change in signature but by adding the OUTs we are changing the | ||
return type. | ||
|
||
``` | ||
DROP FUNCTION brilliance(varchar, int); | ||
CREATE OR REPLACE FUNCTION | ||
brilliance(name varchar = 'Jorge', rank int = 7, out greetings varchar, out word_count int) | ||
AS | ||
```{{execute}} | ||
We left the original signature in place but now we added two OUT parameters: 1) greetings which will hold the full statement | ||
and 2) word_count which will hold the count of characters in the greetings parameter. | ||
Now let's alter the body of the text. | ||
``` | ||
$$ | ||
BEGIN | ||
greetings := (SELECT 'hello ' || name || '! You are number ' || rank); | ||
word_count := length(greetings); | ||
END; | ||
$$ | ||
LANGUAGE plpgsql; | ||
|
||
```{{execute}} | ||
Remember that if we left the language as SQL it would only return the final value and we couldn't really do the assignment of | ||
values to parameters. So we change the language to Pl/PGSQL. Now we get access to the **:=** [assignment operator}(https://www.postgresql.org/docs/11/plpgsql-statements.html). | ||
Because we are using PL/PGSQL we also need to wrap out code in BEGIN and END; statements. Finally, the := operator can only be used | ||
for assignment of a single value or a single row we need to wrap our select statement in ( ) to coerce to a single value. | ||
### Using this new and improved function: | ||
When we use this function: | ||
``` | ||
select brilliance(); | ||
```{{execute}} | ||
Notice we get a different type of result: | ||
``` | ||
workshop=> select brilliance(); | ||
brilliance | ||
-------------------------------------- | ||
("hello Jorge! You are number 7",29) | ||
(1 row) | ||
|
||
``` | ||
We get a single column result with a name matching the function name. For the value we get an array containing our two values. | ||
You can think of this as PostgreSQL coercing all our OUT variables into an array. It would continue appending to | ||
the array for every OUT or INOUT variable we declared. Technically what happened is the our result is actually created an | ||
anonymous record type to hold the output. | ||
Let's make it a bit nicer to read: | ||
``` | ||
select * from brilliance(); | ||
```{{execute}} | ||
Which should give you a result like this: | ||
``` | ||
workshop=> select * from brilliance(); | ||
greetings | word_count | ||
-------------------------------+------------ | ||
hello Jorge! You are number 7 | 29 | ||
(1 row) | ||
|
||
``` | ||
Now we get a row result but the column names match the OUT variable names. Again if we add more OUT variables the result | ||
would just have more columns. | ||
## Different Data Types to Return | ||
So far all we have returning simple values that match base types in SQL. As mentioned earlier you can | ||
return anything you can use to define a column in a table, even your custom defined type. | ||
Quite often you are going to want to return a row in a table or perhaps a whole table (or use them as OUT parameters): | ||
1. RETURNS RECORD - A record can be thought of as a single row in an arbitrary table. | ||
1. RETURNS {tablename} - If you want a row to obey the schema of a table you can just pass in the table name. | ||
1. RETURNS SETOF RECORD - By adding the SETOF to the statement you can now return multiple records (rows) | ||
1. RETURNS SETOF {tablename} - And by extension, this will return multiple rows with a schema that obeys the table schema | ||
Specific to the RETURNS X AS, you can actually define a table in the place of X. For example: | ||
``` | ||
CREATE FUNCTION my-little-table() | ||
RETURNS TABLE (id int, name text, quarter tsrange) | ||
As $$ | ||
``` | ||
## Wrap Up | ||
With that we have concluded our basic introduction to PostgreSQL functions. We did not actually go into specifics of PL/PGSQL | ||
or PL/Python nor did we cover any of the more advanced ways of working with function results like Lateral Joins and such. | ||
Those will be topics for later classes. | ||
The main goal was really to get you to understand the basic structure of functions, how to pass data in and out, and get | ||
your hands dirty. Hopefully you now have a good foundation for diving into [more of](https://www.postgresql.org/docs/current/plpgsql.html) | ||
the [core documentation](https://www.postgresql.org/docs/current/extend.html). |
Oops, something went wrong.