Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Extensible Storage Engine wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Clusterpoint wikipedia , lookup
Open Database Connectivity wikipedia , lookup
Database model wikipedia , lookup
Microsoft SQL Server wikipedia , lookup
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);