11-Libraries, pitfalls, stored procedures, triggersx
Download
Report
Transcript 11-Libraries, pitfalls, stored procedures, triggersx
Libraries, pitfalls,
stored
procedures,
triggers
CMSC 461
Michael Wilson
Libraries to use?
Now
that you’ve got a coding assignment
and you’ve had some time to do your
own research, I’m going to draw attention
to some libraries
From very raw to very fully featured
Won’t
go in total depth
I’d be spending hours on pure syntax
Get
an idea of what kind of approaches
are available
Let’s start with C
Why?
MySQL and PostgreSQL both come with
native C libraries
They’re
pretty raw
Regardless, good to go over
libpq - PostgreSQL
libpq
is PostgreSQL’s built in C library
A lot of other libraries use this under the
covers
Not necessarily something you want to
use if you can avoid it
There are much nicer libraries around
libpq - Connecting
const char *conninfo;
PGconn *conn;
conn = Pqconnectdb(conninfo);
if (Pqstatus(conn) != CONNECTION_OK)
{
/* Error connecting. */
PQfinish(conn);
}
libpq - Querying
PGresult *result = PQexec(conn,
“SELECT * FROM table”);
int numFields = PQnfields(result);
int numRows = PQntuples(result);
/* Get values */
PQclear(result);
libpq – Getting values
for(int i=0; i<numRows; i++)
{
for(int j=0; j<numFields; j++)
{
char *field = PQgetvalue(result, i, j);
}
}
libpq - Thoughts
libpq
is not the kind of library that you’d
want to use if you could help it
C is not exactly the most well suited
language for this kind of task
A lot of plugins and applications use this
under the covers
Good
to know about
At least so you know what a very “basic”
database library looks like
Hibernate
Java
More or less the industry standard for Java DB
interaction
Requires a good bit of up front work, but it
saves us a ton of pain at the end
The following examples assume you’ve
already got database tables
Also, a note: because Hibernate can operate
on multiple table types, it has its own query
language variant called HQL
Hibernate – create class
Create a class that reflects your database
class AddressBook {
private Integer id;
private String phoneNumber;
….
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Hibernate – create class
Class
must be JavaBeans compliant
http://en.wikipedia.org/wiki/JavaBeans
Must
Have
getters/setters for each private variable
Have a default constructor with no arguments
Be serializable
Hibernate – create mapping
The
mapping is an XML file while describes
how to map database tables to your class
Create one mapping file per class
<classname>.hbm.xml
So: AddressBook.hbm.xml
Hibernate – create mapping
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name=“AddressBook” table=“AddressBook”>
<id name=“id” type=“int” column=“id”>
<generator class=“native” />
</id>
<property name=“phoneNumber” column=“phoneNumber”
type=“string” />
….
</class>
</hibernate-mapping>
Hibernate – create mapping
Your
column names need not match up
exactly with the model class you’ve
created
Can name them how you want, as long as
the mapping is appropriate
Generator
values
– how to generate new id
“native” means let the database handle it
Hibernate – getting an
AddressBook entry
SessionFactory factory = new
Configuration().configure().buildSessionFactory();
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
AddressBook ab =
(AddressBook)session.get(AddressBook.class, 5);
Hibernate – update an
AddressBookEntry
SessionFactory factory = new
Configuration().configure().buildSessionFactory();
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
AddressBook ab =
(AddressBook)session.get(AddressBook.class, 5);
ab.setPhoneNumber(“1234567”);
session.update(ab);
tx.commit();
Hibernate - Thoughts
A
bit more up front pain, but afterwards
DB operations are much simpler
If
Don’t have to worry about getting column
5 in row 2
Gets an entire object out of the database
one at a time
you can help it, a library like this is more
along the lines of what you’d want to use
Other libraries?
All
libraries are fair game in this course
There are libraries as nice as Hibernate, as
raw as libpq, and anywhere in between
Depends
on the language you want to
use
There is one pretty common pitfall in
utilizing these libraries in code
Bobby tables
From XKCD: http://xkcd.com/327/
Licensed under a Creative Commons Attribution NonCommercial license
What’s happening here?
So
what really happened with this?
Imagine the query being issued to the
database by a program looked
something like this:
“INSERT INTO Students (Name) VALUES (‘“ +
studentName + “’);
Code is concatenating the string directly
into the query
SQL injection
Bobby
tables’ query issued to the
database:
INSERT INTO Students (Name) VALUES
(‘Robert’); DROP TABLE Students; --’)
Any guess as to what -- is?
How to prevent this?
There
are a number of ways:
Prepared statements
Server
Escaping parameters given to SQL queries
Can
side/client side
be problematic
Data validation (regex)
Prepared statements (server
side)
PostgreSQL supports these server side
Kind of like creating a SQL function
PREPARE addressQuery (int) AS
SELECT * FROM AddressBook where id = $1
Afterwards, to execute the prepared
statement
EXECUTE addressQuery(5);
Prepared statements (server
side)
Parameters
are not recognized as SQL
code fragments
Therefore, problems will not occur
Prepared statements (client
side)
Many
database libraries emulate this
client side
You may not have permission or access to
prepare statements server side
Can do it in the code
Hibernate’s parameterization
String query = “from AddressBook a where
a.id = :id”;
List result = session.createQuery(hql)
.setParameter(“id”, 5)
.list();
Hibernate’s parameterization
Similar
effect without the need for
PREPARE statements DB side
You can use whatever feels more
comfortable for you
I highly recommend using these in your
code, however
Dangers of SQL injection
Hackers
erase debt
Mysql.com compromised by SQL injection
Malware installed onto thousands of
Chinese websites through SQL injection
Stored procedures
Stored
procedures are a really deep,
involved topic
We can only get so far into this
PostgreSQL
got it’s own language for
stored procedures
PL/pgSQL
http://www.postgresql.org/docs/9.3/static/
plpgsql.html
Stored procedures
Functions
can
Return values
Issue SQL queries
Take arguments
Store things into variables (including query
results)
Branch, loop
Defining a stored procedure
CREATE FUNCTION <function-name>([args])
RETURNS <data-type> AS $$
DECLARE
<variables>
BEGIN
<code>
END;
$$ LANGUAGE plpgsql
Declaration block
Here
you can declare variables to be
used in your stored procedure
user_id integer;
quantity numeric(5);
url varchar;
Same
types of data types that are used in
SQL
Defaults are used unless the variable is
assigned
Declaration block assignment
Assignment
url varchar := ‘http://slashdot.org’;
user_id integer := 5;
Can
make variables read only with
CONSTANT
user_id CONSTANT integer := 5;
Code block
This
is where you put your actual code
statements
Regular SQL will work here
You can use variables from the declaration
block here
You can also store things into variables
Arithmetic
Basically like any other language
Code block
Assignment
y := user_id;
SQL
statements
SELECT * FROM AddressBook INTO results;
Selecting
If
INTO a variable
statements
IF var > 5 THEN
RETURN FALSE;
END IF;
Code block
Looping
FOR var IN vars
LOOP
count := count + 1;
END LOOP;
WHILE true i < 5
LOOP
i := i + 1;
END LOOP;
Code block
Raising exceptions
Catching exceptions
RAISE EXCEPTION ‘Message’;
BEGIN
y := 1 / 0;
EXCEPTION
WHEN DIVISION_BY_ZERO THEN
RAISE EXCPETION ‘Cannot divide by zero!’;
END;
Returning values
BEGIN
RETURN 5;
END;
Triggers
What
if we want to specify some sort of
automated behavior when certain
conditions are met?
This is what triggers are for
Triggers
can occur on any sort of data
modification in a table
Insert, update, delete
Triggers per statement or per
row
Triggers
can be marked to occur FOR
EACH ROW
If this is the case, the trigger is called for
each row that a statement modifies
Triggers
can also be marked to occur FOR
EACH STATEMENT
If a statement is executed that affects N
rows, the trigger will only execute once
Triggers
BEFORE
AFTER
The action will trigger BEFORE a statement is
executed
The action will trigger AFTER a statement is
executed
INSTEAD OF
Will occur INSTEAD OF the statement supplied
Can only operate on views, and must be
defined FOR EACH ROW
Triggers
Triggers
in PostgreSQL can only execute
stored procedures
Need to store a procedure first, then
configure a trigger to execute it
Example trigger
Say
we want to automatically populate
our AddressBook with numbers of people
who call us
CREATE TRIGGER populateAddressBook
BEFORE INSERT ON CallList
FOR EACH ROW
WHEN NOT EXISTS(SELECT phoneNumber
from AddressBook)
EXECUTE
AddToAddressBook(NEW.phoneNumber);