De vuelta al pasado con SQL y stored procedures

Post on 10-May-2015

2104 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

El uso de stored procedures está muy difundido entre los administradores de bases de datos como una forma de encapsular la lógica de datos de las aplicaciones. La comunidad de desarrolladores web, sin embargo, nunca los adoptó plenamente porque siempre ha tenido dudas acerca de su portabilidad y mantenibilidad, además de una antipatía generalizada por SQL.De todos modos, la alternativa que se utiliza actualmente, la dupla abstracción de base de datos-ORM, también tiene sus propios problemas: baja performance, subutilización de las funciones avanzadas de bases de datos, y sintaxis de queries ad-hoc que terminan siendo más complicadas que el propio SQL.La creciente popularidad de las bases de datos NoSQL pone de manifiesto que los desarrolladores web contemporáneos están de nuevo dispuestos a considerar librerías de bases de datos específicas del vendedor para el desarrollo de aplicaciones. Entonces veamos qué es lo que tiene para ofrecernos un vendedor en particular: PostgreSQL.En esta charla voy a demostrar que crear una API basada en una mezcla de objetos Ruby sencillos y stored procedures de Postgres puede ser una opción muy convincente como sustituto de ORM.

Transcript

Norman Clarke

Business Vision Ruby Labs@compay

Volver al futuro con SQL y stored procedures

Wednesday, November 9, 11

Wednesday, November 9, 11

Wednesday, November 9, 11

Wednesday, November 9, 11

Lo que les espera...

• Características, ventajas y desventajas de stored procedures

• Una librería experimental basada en stored procedures

• Stored procedures vs. ORM

Wednesday, November 9, 11

Stored Proceduresprogramación "real" con SQL

Wednesday, November 9, 11

postgres=# select greeting();

greeting ------------- hello world!

(1 row)

Wednesday, November 9, 11

1 CREATE FUNCTION greeting()2 RETURNS TEXT AS $$3 BEGIN4 RETURN 'hello world!';5 END;6 $$ LANGUAGE 'plpgsql';

Wednesday, November 9, 11

declarebegin select ... if ... then update ... else while ... loop ... end loop; end if; return ...;end;

Wednesday, November 9, 11

¿Cuántas funciones?Postgres: 2333

Lua: 135

Wednesday, November 9, 11

Ventajas

Wednesday, November 9, 11

Cacheo automáticode consultas

Wednesday, November 9, 11

Menos coordinación entre la BD y Ruby

O Java, Python, Perl, PHP, etc.

Wednesday, November 9, 11

Encapsulación del esquema

Stored Procedures

Esquema Ruby

Wednesday, November 9, 11

Toda la lógica de negocios en SQL

Wednesday, November 9, 11

Wednesday, November 9, 11

No hagan eso por favor

Wednesday, November 9, 11

Squirm

github.com/bvision/squirm

Wednesday, November 9, 11

Squirm

• Azúcar sintáctico para la gema "pg"

• Connection pool básico

• Stored procedures como procs o lambdas

Wednesday, November 9, 11

1 Squirm.connect host: "localhost"2 Squirm.transaction do3 Squirm.exec "SELECT ..." do |result|4 result.to_a5 end6 Squirm.rollback7 end

Wednesday, November 9, 11

1 Squirm do2 connect host: "localhost"3 transaction do4 exec "SELECT ..." do |result|5 result.to_a6 end7 rollback8 end9 end

Wednesday, November 9, 11

1 Squirm do2 exec "CREATE FUNCTION ..."3 proc = procedure "greeting"4 proc.call "Juan"5 #=> "¡hola Juan!"6 end

Wednesday, November 9, 11

1 class Foo 2 3 @@bar = Procedure.load "bar" 4 5 def bar(*args) 6 @@bar.call(*args) 7 end 8 end 9 10 foo = Foo.new11 foo.bar("hello")

Wednesday, November 9, 11

GET followers/idsGET friends/idsGET lists/allGET favorites GET statuses/home_timelineGET statuses/mentionsGET statuses/user_timelineGET direct_messages

Wednesday, November 9, 11

SELECT followers.ids()SELECT friends.ids()SELECT lists.all()SELECT favorites() SELECT statuses.home_timeline()SELECT statuses.mentions()SELECT statuses.user_timeline()SELECT direct_messages()

Wednesday, November 9, 11

Squirm Model

github.com/bvision/squirm_model

Wednesday, November 9, 11

Squirm Model

• Generador de tablas, procedures

• SQL "scaffolding"

• Active Model

Wednesday, November 9, 11

$ squirm table person id email birth_date access_time bio

1 CREATE TABLE "person" (2 "id" SERIAL NOT NULL PRIMARY KEY,3 "email" VARCHAR(64) NOT NULL UNIQUE,4 "birth_date" DATE,5 "access_time" TIMESTAMP WITH TIME ZONE,6 "bio" TEXT7 );

Wednesday, November 9, 11

$ squirm table person id created_at

1 CREATE TABLE "person" ( 2 "id" SERIAL NOT NULL PRIMARY KEY, 3 "created_at" TIMESTAMP WITH TIME ZONE NOT NULL 4 ); 5 6 CREATE OR REPLACE FUNCTION "update_person_created_at_timestamp"() 7 RETURNS TRIGGER AS $$ 8 BEGIN 9 NEW.created_at = NOW();10 RETURN NEW;11 END;12 $$ LANGUAGE 'plpgsql';13 14 CREATE TRIGGER "update_person_created_at_timestamp"15 BEFORE INSERT ON "person"16 FOR EACH ROW EXECUTE PROCEDURE "update_person_created_at_timestamp"();

Wednesday, November 9, 11

$ squirm table person id email --api

CREATE TABLE "person" ...CREATE SCHEMA "person" ...CREATE FUNCTION "person.get" ...CREATE FUNCTION "person.create" ...CREATE FUNCTION "person.update" ...CREATE FUNCTION "person.delete" ...

Wednesday, November 9, 11

1 class Person 2 extend Squirm::Model ... 3 validates_presence_of :name 4 end 5 6 Person.create(...) 7 @person = Person.find(1) 8 @person.valid? 9 @person.to_json10 redirect_to @person

Wednesday, November 9, 11

1 class Person 2 extend Squirm::Model 3 4 sample do |s| 5 s.id = 1 6 s.name = "Juan Fulano" 7 end 8 9 validates_presence_of :name10 end

Wednesday, November 9, 11

1 class PersonTest < Test::Unit::TestCase2 def test_create3 assert Person.create(Person.sample)4 end5 end

Wednesday, November 9, 11

1 Squirm do 2 connect host: "localhost" 3 4 exec Person.to_ddl 5 6 Person.finalize 7 8 p = Person.create name: "John" 9 p.update name: "Johnny"10 p.delete11 end

Wednesday, November 9, 11

ROFLSCALE

0 7.5 15 22.5 30

Squirm Model ActiveRecord

Benchmarks

Wednesday, November 9, 11

¿Por qué no usar un ORM?

Wednesday, November 9, 11

Usen los ORM

• Active Record

• DataMapper

• Sequel

• otros

Wednesday, November 9, 11

Pero conozcan sus defectos

Wednesday, November 9, 11

Exhibition.all( :run_time.gt => 2, :run_time.lt => 5)

run_time > 1 AND run_time < 5

...you might be wondering how we can specify conditions beyond equality without resorting to SQL. Well, thanks to some clever additions to the Symbol class, it’s easy!

Wednesday, November 9, 11

table = Product.arel_tableProduct.where( table[:price].eq(2.99). or(table[:name].matches("%foo"))).to_sql

#=> "WHERE price = 2.99 OR name LIKE '%foo'"

railscasts.com/episodes/215-advanced-queries-in-rails-3

Wednesday, November 9, 11

SQL (mal) generado

Wednesday, November 9, 11

La abstracción dificulta el uso de features

avanzados

Wednesday, November 9, 11

Los stored procedures ofrecen una alternativa

interesante

Wednesday, November 9, 11

"Pensemos diferente"

Wednesday, November 9, 11

Nihil sub sole novum

Wednesday, November 9, 11

Postgres y MySQL están muy desaprovechados

Wednesday, November 9, 11

No usemos abstracciones innecesarias

Wednesday, November 9, 11

¡Gracias!

Wednesday, November 9, 11

Wednesday, November 9, 11

Obelisco: flickr.com/photos/budgetplaces/4173902613/Matz: flickr.com/photos/rrrodrigo/2394122680/

Gracias, fotógrafos

Wednesday, November 9, 11

top related