mirror of https://github.com/postgres/postgres
parent
c13a64d7fb
commit
e9491eb91c
@ -0,0 +1,171 @@ |
||||
#! /usr/local/bin/python |
||||
# advanced.py - demo of advanced features of PostGres. Some may not be ANSI. |
||||
# inspired from the Postgres tutorial |
||||
# adapted to Python 1995 by Pascal Andre |
||||
|
||||
print "__________________________________________________________________" |
||||
print "MODULE ADVANCED.PY : ADVANCED POSTGRES SQL COMMANDS TUTORIAL" |
||||
print |
||||
print "This module is designed for being imported from python prompt" |
||||
print |
||||
print "In order to run the samples included here, first create a connection" |
||||
print "using : cnx = advanced.connect(...)" |
||||
print "then start the demo with: advanced.demo(cnx)" |
||||
print "__________________________________________________________________" |
||||
|
||||
from pgtools import * |
||||
from pgext import * |
||||
|
||||
# inheritance features |
||||
def inherit_demo(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Inheritance:" |
||||
print "-- a table can inherit from zero or more tables. A query" |
||||
print "-- can reference either all rows of a table or all rows " |
||||
print "-- of a table plus all of its descendants." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- For example, the capitals table inherits from cities table." |
||||
print "-- (It inherits all data fields from cities.)" |
||||
print |
||||
print "CREATE TABLE cities (" |
||||
print " name text," |
||||
print " population float8," |
||||
print " altitude int" |
||||
print ")" |
||||
print |
||||
print "CREATE TABLE capitals (" |
||||
print " state varchar(2)" |
||||
print ") INHERITS (cities)" |
||||
pgcnx.query("CREATE TABLE cities (" \ |
||||
"name text," \ |
||||
"population float8," \ |
||||
"altitude int)") |
||||
pgcnx.query("CREATE TABLE capitals (" \ |
||||
"state varchar(2)) INHERITS (cities)") |
||||
wait_key() |
||||
print |
||||
print "-- now, let's populate the tables" |
||||
print |
||||
print "INSERT INTO cities VALUES ('San Francisco', 7.24E+5, 63)" |
||||
print "INSERT INTO cities VALUES ('Las Vegas', 2.583E+5, 2174)" |
||||
print "INSERT INTO cities VALUES ('Mariposa', 1200, 1953)" |
||||
print |
||||
print "INSERT INTO capitals VALUES ('Sacramento', 3.694E+5, 30, 'CA')" |
||||
print "INSERT INTO capitals VALUES ('Madison', 1.913E+5, 845, 'WI')" |
||||
print |
||||
pgcnx.query( |
||||
"INSERT INTO cities VALUES ('San Francisco', 7.24E+5, 63)") |
||||
pgcnx.query( |
||||
"INSERT INTO cities VALUES ('Las Vegas', 2.583E+5, 2174)") |
||||
pgcnx.query( |
||||
"INSERT INTO cities VALUES ('Mariposa', 1200, 1953)") |
||||
pgcnx.query("INSERT INTO capitals" \ |
||||
" VALUES ('Sacramento', 3.694E+5, 30, 'CA')") |
||||
pgcnx.query("INSERT INTO capitals" \ |
||||
" VALUES ('Madison', 1.913E+5, 845, 'WI')") |
||||
print |
||||
print "SELECT * FROM cities" |
||||
print pgcnx.query("SELECT * FROM cities") |
||||
print "SELECT * FROM capitals" |
||||
print pgcnx.query("SELECT * FROM capitals") |
||||
print |
||||
print "-- like before, a regular query references rows of the base" |
||||
print "-- table only" |
||||
print |
||||
print "SELECT name, altitude" |
||||
print "FROM cities" |
||||
print "WHERE altitude > 500;" |
||||
print pgcnx.query("SELECT name, altitude " \ |
||||
"FROM cities " \ |
||||
"WHERE altitude > 500") |
||||
print |
||||
print "-- on the other hand, you can find all cities, including " |
||||
print "-- capitals, that are located at an altitude of 500 'ft " |
||||
print "-- or higher by:" |
||||
print |
||||
print "SELECT c.name, c.altitude" |
||||
print "FROM cities* c" |
||||
print "WHERE c.altitude > 500" |
||||
print pgcnx.query("SELECT c.name, c.altitude " \ |
||||
"FROM cities* c " \ |
||||
"WHERE c.altitude > 500") |
||||
|
||||
# arrays attributes |
||||
def array_demo(pgcnx): |
||||
print "----------------------" |
||||
print "-- Arrays:" |
||||
print "-- attributes can be arrays of base types or user-defined " |
||||
print "-- types" |
||||
print "----------------------" |
||||
print |
||||
print "CREATE TABLE sal_emp (" |
||||
print " name text," |
||||
print " pay_by_quarter int4[]," |
||||
print " schedule text[][]" |
||||
print ")" |
||||
pgcnx.query("CREATE TABLE sal_emp (" \ |
||||
"name text," \ |
||||
"pay_by_quarter int4[]," \ |
||||
"schedule text[][])") |
||||
wait_key() |
||||
print |
||||
print "-- insert instances with array attributes. " |
||||
print " Note the use of braces" |
||||
print |
||||
print "INSERT INTO sal_emp VALUES (" |
||||
print " 'Bill'," |
||||
print " '{10000,10000,10000,10000}'," |
||||
print " '{{\"meeting\", \"lunch\"}, {}}')" |
||||
print |
||||
print "INSERT INTO sal_emp VALUES (" |
||||
print " 'Carol'," |
||||
print " '{20000,25000,25000,25000}'," |
||||
print " '{{\"talk\", \"consult\"}, {\"meeting\"}}')" |
||||
print |
||||
pgcnx.query("INSERT INTO sal_emp VALUES (" \ |
||||
"'Bill', '{10000,10000,10000,10000}'," \ |
||||
"'{{\"meeting\", \"lunch\"}, {}}')") |
||||
pgcnx.query("INSERT INTO sal_emp VALUES (" \ |
||||
"'Carol', '{20000,25000,25000,25000}'," \ |
||||
"'{{\"talk\", \"consult\"}, {\"meeting\"}}')") |
||||
wait_key() |
||||
print |
||||
print "----------------------" |
||||
print "-- queries on array attributes" |
||||
print "----------------------" |
||||
print |
||||
print "SELECT name FROM sal_emp WHERE" |
||||
print " sal_emp.pay_by_quarter[1] <> sal_emp.pay_by_quarter[2]" |
||||
print |
||||
print pgcnx.query("SELECT name FROM sal_emp WHERE " \ |
||||
"sal_emp.pay_by_quarter[1] <> sal_emp.pay_by_quarter[2]") |
||||
print |
||||
print "-- retrieve third quarter pay of all employees" |
||||
print |
||||
print "SELECT sal_emp.pay_by_quarter[3] FROM sal_emp" |
||||
print |
||||
print pgcnx.query("SELECT sal_emp.pay_by_quarter[3] FROM sal_emp") |
||||
print |
||||
print "-- select subarrays" |
||||
print |
||||
print "SELECT sal_emp.schedule[1:2][1:1] FROM sal_emp WHERE " |
||||
print " sal_emp.name = 'Bill'" |
||||
print pgcnx.query("SELECT sal_emp.schedule[1:2][1:1] FROM sal_emp WHERE " \ |
||||
"sal_emp.name = 'Bill'") |
||||
|
||||
# base cleanup |
||||
def demo_cleanup(pgcnx): |
||||
print "-- clean up (you must remove the children first)" |
||||
print "DROP TABLE sal_emp" |
||||
print "DROP TABLE capitals" |
||||
print "DROP TABLE cities;" |
||||
pgcnx.query("DROP TABLE sal_emp") |
||||
pgcnx.query("DROP TABLE capitals") |
||||
pgcnx.query("DROP TABLE cities") |
||||
|
||||
# main demo function |
||||
def demo(pgcnx): |
||||
inherit_demo(pgcnx) |
||||
array_demo(pgcnx) |
||||
demo_cleanup(pgcnx) |
||||
@ -0,0 +1,284 @@ |
||||
#! /usr/local/bin/python |
||||
# basics.py - basic SQL commands tutorial |
||||
# inspired from the Postgres95 tutorial |
||||
# adapted to Python 1995 by Pascal ANDRE |
||||
|
||||
print "__________________________________________________________________" |
||||
print "MODULE BASICS.PY : BASIC SQL COMMANDS TUTORIAL" |
||||
print |
||||
print "This module is designed for being imported from python prompt" |
||||
print |
||||
print "In order to run the samples included here, first create a connection" |
||||
print "using : cnx = basics.connect(...)" |
||||
print "then start the demo with: basics.demo(cnx)" |
||||
print "__________________________________________________________________" |
||||
|
||||
from pgext import * |
||||
from pgtools import * |
||||
|
||||
# table creation commands |
||||
def create_table(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Creating a table:" |
||||
print "-- a CREATE TABLE is used to create base tables. POSTGRES" |
||||
print "-- SQL has its own set of built-in types. (Note that" |
||||
print "-- keywords are case-insensitive but identifiers are " |
||||
print "-- case-sensitive.)" |
||||
print "-----------------------------" |
||||
print |
||||
print "Sending query :" |
||||
print "CREATE TABLE weather (" |
||||
print " city varchar(80)," |
||||
print " temp_lo int," |
||||
print " temp_hi int," |
||||
print " prcp float8," |
||||
print " date date" |
||||
print ")" |
||||
pgcnx.query("CREATE TABLE weather (city varchar(80), temp_lo int," \ |
||||
"temp_hi int, prcp float8, date date)") |
||||
print |
||||
print "Sending query :" |
||||
print "CREATE TABLE cities (" |
||||
print " name varchar(80)," |
||||
print " location point" |
||||
print ")" |
||||
pgcnx.query("CREATE TABLE cities (" \ |
||||
"name varchar(80)," \ |
||||
"location point)") |
||||
|
||||
# data insertion commands |
||||
def insert_data(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Inserting data:" |
||||
print "-- an INSERT statement is used to insert a new row into" |
||||
print "-- a table. There are several ways you can specify what" |
||||
print "-- columns the data should go to." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- 1. the simplest case is when the list of value correspond to" |
||||
print "-- the order of the columns specified in CREATE TABLE." |
||||
print |
||||
print "Sending query :" |
||||
print "INSERT INTO weather " |
||||
print " VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994')" |
||||
pgcnx.query("INSERT INTO weather " \ |
||||
"VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994')") |
||||
print |
||||
print "Sending query :" |
||||
print "INSERT INTO cities " |
||||
print " VALUES ('San Francisco', '(-194.0, 53.0)')" |
||||
pgcnx.query("INSERT INTO cities " \ |
||||
"VALUES ('San Francisco', '(-194.0, 53.0)')") |
||||
print |
||||
wait_key() |
||||
print "-- 2. you can also specify what column the values correspond " |
||||
print " to. (The columns can be specified in any order. You may " |
||||
print " also omit any number of columns. eg. unknown precipitation" |
||||
print " below)" |
||||
print "Sending query :" |
||||
print "INSERT INTO weather (city, temp_lo, temp_hi, prcp, date)" |
||||
print " VALUES ('San Francisco', 43, 57, 0.0, '11/29/1994')" |
||||
pgcnx.query("INSERT INTO weather (date, city, temp_hi, temp_lo)" \ |
||||
"VALUES ('11/29/1994', 'Hayward', 54, 37)") |
||||
|
||||
# direct selection commands |
||||
def select_data1(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Retrieving data:" |
||||
print "-- a SELECT statement is used for retrieving data. The " |
||||
print "-- basic syntax is:" |
||||
print "-- SELECT columns FROM tables WHERE predicates" |
||||
print "-----------------------------" |
||||
print |
||||
print "-- a simple one would be the query:" |
||||
print "SELECT * FROM weather" |
||||
print |
||||
print "The result is :" |
||||
q = pgcnx.query("SELECT * FROM weather") |
||||
print q |
||||
print |
||||
print "-- you may also specify expressions in the target list (the " |
||||
print "-- 'AS column' specifies the column name of the result. It is " |
||||
print "-- optional.)" |
||||
print "The query :" |
||||
print " SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date " |
||||
print " FROM weather" |
||||
print "Gives :" |
||||
print pgcnx.query("SELECT city, (temp_hi+temp_lo)/2 " \ |
||||
"AS temp_avg, date FROM weather") |
||||
print |
||||
print "-- if you want to retrieve rows that satisfy certain condition" |
||||
print "-- (ie. a restriction), specify the condition in WHERE. The " |
||||
print "-- following retrieves the weather of San Francisco on rainy " |
||||
print "-- days." |
||||
print "SELECT *" |
||||
print "FROM weather" |
||||
print "WHERE city = 'San Francisco' " |
||||
print " and prcp > 0.0" |
||||
print pgcnx.query("SELECT * FROM weather WHERE city = 'San Francisco'" \ |
||||
" AND prcp > 0.0") |
||||
print |
||||
print "-- here is a more complicated one. Duplicates are removed when " |
||||
print "-- DISTINCT is specified. ORDER BY specifies the column to sort" |
||||
print "-- on. (Just to make sure the following won't confuse you, " |
||||
print "-- DISTINCT and ORDER BY can be used separately.)" |
||||
print "SELECT DISTINCT city" |
||||
print "FROM weather" |
||||
print "ORDER BY city;" |
||||
print pgcnx.query("SELECT DISTINCT city FROM weather ORDER BY city") |
||||
|
||||
# selection to a temporary table |
||||
def select_data2(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Retrieving data into other classes:" |
||||
print "-- a SELECT ... INTO statement can be used to retrieve " |
||||
print "-- data into another class." |
||||
print "-----------------------------" |
||||
print |
||||
print "The query :" |
||||
print "SELECT * INTO TABLE temp " |
||||
print "FROM weather" |
||||
print "WHERE city = 'San Francisco' " |
||||
print " and prcp > 0.0" |
||||
pgcnx.query("SELECT * INTO TABLE temp FROM weather " \ |
||||
"WHERE city = 'San Francisco' and prcp > 0.0") |
||||
print "Fills the table temp, that can be listed with :" |
||||
print "SELECT * from temp" |
||||
print pgcnx.query("SELECT * from temp") |
||||
|
||||
# aggregate creation commands |
||||
def create_aggregate(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Aggregates" |
||||
print "-----------------------------" |
||||
print |
||||
print "Let's consider the query :" |
||||
print "SELECT max(temp_lo)" |
||||
print "FROM weather;" |
||||
print pgcnx.query("SELECT max(temp_lo) FROM weather") |
||||
print |
||||
print "-- Aggregate with GROUP BY" |
||||
print "SELECT city, max(temp_lo)" |
||||
print "FROM weather " |
||||
print "GROUP BY city;" |
||||
print pgcnx.query( "SELECT city, max(temp_lo)" \ |
||||
"FROM weather GROUP BY city") |
||||
|
||||
# table join commands |
||||
def join_table(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Joining tables:" |
||||
print "-- queries can access multiple tables at once or access" |
||||
print "-- the same table in such a way that multiple instances" |
||||
print "-- of the table are being processed at the same time." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- suppose we want to find all the records that are in the " |
||||
print "-- temperature range of other records. W1 and W2 are aliases " |
||||
print "--for weather." |
||||
print |
||||
print "SELECT W1.city, W1.temp_lo, W1.temp_hi, " |
||||
print " W2.city, W2.temp_lo, W2.temp_hi" |
||||
print "FROM weather W1, weather W2" |
||||
print "WHERE W1.temp_lo < W2.temp_lo " |
||||
print " and W1.temp_hi > W2.temp_hi" |
||||
print |
||||
print pgcnx.query("SELECT W1.city, W1.temp_lo, W1.temp_hi, " \ |
||||
"W2.city, W2.temp_lo, W2.temp_hi FROM weather W1, weather W2 "\ |
||||
"WHERE W1.temp_lo < W2.temp_lo and W1.temp_hi > W2.temp_hi") |
||||
print |
||||
print "-- let's join two tables. The following joins the weather table" |
||||
print "-- and the cities table." |
||||
print |
||||
print "SELECT city, location, prcp, date" |
||||
print "FROM weather, cities" |
||||
print "WHERE name = city" |
||||
print |
||||
print pgcnx.query("SELECT city, location, prcp, date FROM weather, cities"\ |
||||
" WHERE name = city") |
||||
print |
||||
print "-- since the column names are all different, we don't have to " |
||||
print "-- specify the table name. If you want to be clear, you can do " |
||||
print "-- the following. They give identical results, of course." |
||||
print |
||||
print "SELECT w.city, c.location, w.prcp, w.date" |
||||
print "FROM weather w, cities c" |
||||
print "WHERE c.name = w.city;" |
||||
print |
||||
print pgcnx.query("SELECT w.city, c.location, w.prcp, w.date " \ |
||||
"FROM weather w, cities c WHERE c.name = w.city") |
||||
|
||||
# data updating commands |
||||
def update_data(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Updating data:" |
||||
print "-- an UPDATE statement is used for updating data. " |
||||
print "-----------------------------" |
||||
print |
||||
print "-- suppose you discover the temperature readings are all off by" |
||||
print "-- 2 degrees as of Nov 28, you may update the data as follow:" |
||||
print |
||||
print "UPDATE weather" |
||||
print " SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2" |
||||
print " WHERE date > '11/28/1994'" |
||||
print |
||||
pgcnx.query("UPDATE weather " \ |
||||
"SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2" \ |
||||
"WHERE date > '11/28/1994'") |
||||
print |
||||
print "SELECT * from weather" |
||||
print pgcnx.query("SELECT * from weather") |
||||
|
||||
# data deletion commands |
||||
def delete_data(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Deleting data:" |
||||
print "-- a DELETE statement is used for deleting rows from a " |
||||
print "-- table." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- suppose you are no longer interested in the weather of " |
||||
print "-- Hayward, you can do the following to delete those rows from" |
||||
print "-- the table" |
||||
print |
||||
print "DELETE FROM weather WHERE city = 'Hayward'" |
||||
pgcnx.query("DELETE FROM weather WHERE city = 'Hayward'") |
||||
print |
||||
print "SELECT * from weather" |
||||
print |
||||
print pgcnx.query("SELECT * from weather") |
||||
print |
||||
print "-- you can also delete all the rows in a table by doing the " |
||||
print "-- following. (This is different from DROP TABLE which removes " |
||||
print "-- the table in addition to the removing the rows.)" |
||||
print |
||||
print "DELETE FROM weather" |
||||
pgcnx.query("DELETE FROM weather") |
||||
print |
||||
print "SELECT * from weather" |
||||
print pgcnx.query("SELECT * from weather") |
||||
|
||||
# table removal commands |
||||
def remove_table(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Removing the tables:" |
||||
print "-- DROP TABLE is used to remove tables. After you have" |
||||
print "-- done this, you can no longer use those tables." |
||||
print "-----------------------------" |
||||
print |
||||
print "DROP TABLE weather, cities, temp" |
||||
pgcnx.query("DROP TABLE weather, cities, temp") |
||||
|
||||
# main demo function |
||||
def demo(pgcnx): |
||||
create_table(pgcnx) |
||||
wait_key() |
||||
insert_data(pgcnx) |
||||
wait_key() |
||||
select_data1(pgcnx) |
||||
select_data2(pgcnx) |
||||
create_aggregate(pgcnx) |
||||
join_table(pgcnx) |
||||
update_data(pgcnx) |
||||
delete_data(pgcnx) |
||||
remove_table(pgcnx) |
||||
@ -0,0 +1,193 @@ |
||||
# func.py - demonstrate the use of SQL functions |
||||
# inspired from the PostgreSQL tutorial |
||||
# adapted to Python 1995 by Pascal ANDRE |
||||
|
||||
print "__________________________________________________________________" |
||||
print "MODULE FUNC.PY : SQL FUNCTION DEFINITION TUTORIAL" |
||||
print |
||||
print "This module is designed for being imported from python prompt" |
||||
print |
||||
print "In order to run the samples included here, first create a connection" |
||||
print "using : cnx = func.connect(...)" |
||||
print "then start the demo with: func.demo(cnx)" |
||||
print "__________________________________________________________________" |
||||
|
||||
from pgtools import * |
||||
from pgext import * |
||||
|
||||
# basic functions declaration |
||||
def base_func(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Creating SQL Functions on Base Types" |
||||
print "-- a CREATE FUNCTION statement lets you create a new " |
||||
print "-- function that can be used in expressions (in SELECT, " |
||||
print "-- INSERT, etc.). We will start with functions that " |
||||
print "-- return values of base types." |
||||
print "-----------------------------" |
||||
print |
||||
print "--" |
||||
print "-- let's create a simple SQL function that takes no arguments" |
||||
print "-- and returns 1" |
||||
print |
||||
print "CREATE FUNCTION one() RETURNS int4" |
||||
print " AS 'SELECT 1 as ONE' LANGUAGE 'sql'" |
||||
pgcnx.query("CREATE FUNCTION one() RETURNS int4 " \ |
||||
"AS 'SELECT 1 as ONE' LANGUAGE 'sql'") |
||||
wait_key() |
||||
print |
||||
print "--" |
||||
print "-- functions can be used in any expressions (eg. in the target" |
||||
print "-- list or qualifications)" |
||||
print |
||||
print "SELECT one() AS answer" |
||||
print pgcnx.query("SELECT one() AS answer") |
||||
print |
||||
print "--" |
||||
print "-- here's how you create a function that takes arguments. The" |
||||
print "-- following function returns the sum of its two arguments:" |
||||
print |
||||
print "CREATE FUNCTION add_em(int4, int4) RETURNS int4" |
||||
print " AS 'SELECT $1 + $2' LANGUAGE 'sql'" |
||||
pgcnx.query("CREATE FUNCTION add_em(int4, int4) RETURNS int4 " \ |
||||
"AS 'SELECT $1 + $2' LANGUAGE 'sql'") |
||||
print |
||||
print "SELECT add_em(1, 2) AS answer" |
||||
print pgcnx.query("SELECT add_em(1, 2) AS answer") |
||||
|
||||
# functions on composite types |
||||
def comp_func(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Creating SQL Functions on Composite Types" |
||||
print "-- it is also possible to create functions that return" |
||||
print "-- values of composite types." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- before we create more sophisticated functions, let's " |
||||
print "-- populate an EMP table" |
||||
print |
||||
print "CREATE TABLE EMP (" |
||||
print " name text," |
||||
print " salary int4," |
||||
print " age int4," |
||||
print " dept varchar(16)" |
||||
print ")" |
||||
pgcnx.query("CREATE TABLE EMP (" \ |
||||
"name text," \ |
||||
"salary int4," \ |
||||
"age int4," \ |
||||
"dept varchar(16))") |
||||
print |
||||
print "INSERT INTO EMP VALUES ('Sam', 1200, 16, 'toy')" |
||||
print "INSERT INTO EMP VALUES ('Claire', 5000, 32, 'shoe')" |
||||
print "INSERT INTO EMP VALUES ('Andy', -1000, 2, 'candy')" |
||||
print "INSERT INTO EMP VALUES ('Bill', 4200, 36, 'shoe')" |
||||
print "INSERT INTO EMP VALUES ('Ginger', 4800, 30, 'candy')" |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Sam', 1200, 16, 'toy')") |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Claire', 5000, 32, 'shoe')") |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Andy', -1000, 2, 'candy')") |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Bill', 4200, 36, 'shoe')") |
||||
pgcnx.query("INSERT INTO EMP VALUES ('Ginger', 4800, 30, 'candy')") |
||||
wait_key() |
||||
print |
||||
print "-- the argument of a function can also be a tuple. For " |
||||
print "-- instance, double_salary takes a tuple of the EMP table" |
||||
print |
||||
print "CREATE FUNCTION double_salary(EMP) RETURNS int4" |
||||
print " AS 'SELECT $1.salary * 2 AS salary' LANGUAGE 'sql'" |
||||
pgcnx.query("CREATE FUNCTION double_salary(EMP) RETURNS int4 " \ |
||||
"AS 'SELECT $1.salary * 2 AS salary' LANGUAGE 'sql'") |
||||
print |
||||
print "SELECT name, double_salary(EMP) AS dream" |
||||
print "FROM EMP" |
||||
print "WHERE EMP.dept = 'toy'" |
||||
print pgcnx.query("SELECT name, double_salary(EMP) AS dream " \ |
||||
"FROM EMP WHERE EMP.dept = 'toy'") |
||||
print |
||||
print "-- the return value of a function can also be a tuple. However," |
||||
print "-- make sure that the expressions in the target list is in the " |
||||
print "-- same order as the columns of EMP." |
||||
print |
||||
print "CREATE FUNCTION new_emp() RETURNS EMP" |
||||
print " AS 'SELECT \'None\'::text AS name," |
||||
print " 1000 AS salary," |
||||
print " 25 AS age," |
||||
print " \'none\'::varchar(16) AS dept'" |
||||
print " LANGUAGE 'sql'" |
||||
pgcnx.query("CREATE FUNCTION new_emp() RETURNS EMP " \ |
||||
"AS 'SELECT \\\'None\\\'::text AS name, " \ |
||||
"1000 AS salary, " \ |
||||
"25 AS age, " \ |
||||
"\\\'none\\\'::varchar(16) AS dept' " \ |
||||
"LANGUAGE 'sql'") |
||||
wait_key() |
||||
print |
||||
print "-- you can then project a column out of resulting the tuple by" |
||||
print "-- using the \"function notation\" for projection columns. " |
||||
print "-- (ie. bar(foo) is equivalent to foo.bar) Note that we don't" |
||||
print "-- support new_emp().name at this moment." |
||||
print |
||||
print "SELECT name(new_emp()) AS nobody" |
||||
print pgcnx.query("SELECT name(new_emp()) AS nobody") |
||||
print |
||||
print "-- let's try one more function that returns tuples" |
||||
print "CREATE FUNCTION high_pay() RETURNS setof EMP" |
||||
print " AS 'SELECT * FROM EMP where salary > 1500'" |
||||
print " LANGUAGE 'sql'" |
||||
pgcnx.query("CREATE FUNCTION high_pay() RETURNS setof EMP " \ |
||||
"AS 'SELECT * FROM EMP where salary > 1500' " \ |
||||
"LANGUAGE 'sql'") |
||||
print |
||||
print "SELECT name(high_pay()) AS overpaid" |
||||
print pgcnx.query("SELECT name(high_pay()) AS overpaid") |
||||
|
||||
# function with multiple SQL commands |
||||
def mult_func(pgcnx): |
||||
print "-----------------------------" |
||||
print "-- Creating SQL Functions with multiple SQL statements" |
||||
print "-- you can also create functions that do more than just a" |
||||
print "-- SELECT." |
||||
print "-----------------------------" |
||||
print |
||||
print "-- you may have noticed that Andy has a negative salary. We'll" |
||||
print "-- create a function that removes employees with negative " |
||||
print "-- salaries." |
||||
print |
||||
print "SELECT * FROM EMP" |
||||
print pgcnx.query("SELECT * FROM EMP") |
||||
print |
||||
print "CREATE FUNCTION clean_EMP () RETURNS int4" |
||||
print " AS 'DELETE FROM EMP WHERE EMP.salary <= 0" |
||||
print " SELECT 1 AS ignore_this'" |
||||
print " LANGUAGE 'sql'" |
||||
pgcnx.query("CREATE FUNCTION clean_EMP () RETURNS int4 AS 'DELETE FROM EMP WHERE EMP.salary <= 0; SELECT 1 AS ignore_this' LANGUAGE 'sql'") |
||||
print |
||||
print "SELECT clean_EMP()" |
||||
print pgcnx.query("SELECT clean_EMP()") |
||||
print |
||||
print "SELECT * FROM EMP" |
||||
print pgcnx.query("SELECT * FROM EMP") |
||||
|
||||
# base cleanup |
||||
def demo_cleanup(pgcnx): |
||||
print "-- remove functions that were created in this file" |
||||
print |
||||
print "DROP FUNCTION clean_EMP()" |
||||
print "DROP FUNCTION high_pay()" |
||||
print "DROP FUNCTION new_emp()" |
||||
print "DROP FUNCTION add_em(int4, int4)" |
||||
print "DROP FUNCTION one()" |
||||
print |
||||
print "DROP TABLE EMP" |
||||
pgcnx.query("DROP FUNCTION clean_EMP()") |
||||
pgcnx.query("DROP FUNCTION high_pay()") |
||||
pgcnx.query("DROP FUNCTION new_emp()") |
||||
pgcnx.query("DROP FUNCTION add_em(int4, int4)") |
||||
pgcnx.query("DROP FUNCTION one()") |
||||
pgcnx.query("DROP TABLE EMP") |
||||
|
||||
# main demo function |
||||
def demo(pgcnx): |
||||
base_func(pgcnx) |
||||
comp_func(pgcnx) |
||||
mult_func(pgcnx) |
||||
demo_cleanup(pgcnx) |
||||
@ -0,0 +1,11 @@ |
||||
#! /usr/local/bin/python |
||||
|
||||
import string |
||||
|
||||
# change this if you have it somewhere else |
||||
for l in open("/usr/local/pgsql/src/include/catalog/pg_type.h").readlines(): |
||||
tokens = string.split(l) |
||||
if len(tokens) == 0 or tokens[0] != "#define": continue |
||||
|
||||
if tokens[1] in ('CASHOID', 'INT2OID', 'INT4OID', 'OIDOID', 'FLOAT4OID', 'FLOAT8OID'): |
||||
print l, |
||||
@ -0,0 +1,223 @@ |
||||
# pgutil.py |
||||
# Written by D'Arcy J.M. Cain |
||||
|
||||
# This library implements some basic database management stuff |
||||
# It includes the pg module and builds on it |
||||
|
||||
from _pg import * |
||||
import string, re, sys |
||||
|
||||
# utility function |
||||
# We expect int, seq, decimal, text or date (more later) |
||||
def _quote(d, t): |
||||
if t in ['int', 'decimal', 'seq']: |
||||
if d == "": return 0 |
||||
return "%s" % d |
||||
|
||||
if t == 'bool': |
||||
if string.upper(d) in ['T', 'TRUE', 'Y', 'YES', 1, '1', 'ON']: |
||||
return "'t'" |
||||
else: |
||||
return "'f'" |
||||
|
||||
if d == "": return "null" |
||||
return "'%s'" % string.strip(re.sub('\'', '\'\'', "%s" % d)) |
||||
|
||||
class DB: |
||||
"""This class wraps the pg connection type""" |
||||
|
||||
def __init__(self, *args): |
||||
self.db = apply(connect, args) |
||||
self.attnames = {} |
||||
self.pkeys = {} |
||||
self.debug = None # For debugging scripts, set to output format |
||||
# that takes a single string arg. For example |
||||
# in a CGI set to "%s<BR>" |
||||
|
||||
# Get all the primary keys at once |
||||
for rel, att in self.db.query("""SELECT |
||||
pg_class.relname, pg_attribute.attname |
||||
FROM pg_class, pg_attribute, pg_index |
||||
WHERE pg_class.oid = pg_attribute.attrelid AND |
||||
pg_class.oid = pg_index.indrelid AND |
||||
pg_index.indkey[0] = pg_attribute.attnum AND |
||||
pg_index.indisprimary = 't'""").getresult(): |
||||
self.pkeys[rel] = att |
||||
|
||||
def pkey(self, cl): |
||||
# will raise an exception if primary key doesn't exist |
||||
return self.pkeys[cl] |
||||
|
||||
def get_attnames(self, cl): |
||||
# May as well cache them |
||||
if self.attnames.has_key(cl): |
||||
return self.attnames[cl] |
||||
|
||||
query = """SELECT pg_attribute.attname, pg_type.typname |
||||
FROM pg_class, pg_attribute, pg_type |
||||
WHERE pg_class.relname = '%s' AND |
||||
pg_attribute.attnum > 0 AND |
||||
pg_attribute.attrelid = pg_class.oid AND |
||||
pg_attribute.atttypid = pg_type.oid""" |
||||
|
||||
l = {} |
||||
for attname, typname in self.db.query(query % cl).getresult(): |
||||
if re.match("^int", typname): |
||||
l[attname] = 'int' |
||||
elif re.match("^oid", typname): |
||||
l[attname] = 'int' |
||||
elif re.match("^text", typname): |
||||
l[attname] = 'text' |
||||
elif re.match("^char", typname): |
||||
l[attname] = 'text' |
||||
elif re.match("^name", typname): |
||||
l[attname] = 'text' |
||||
elif re.match("^abstime", typname): |
||||
l[attname] = 'date' |
||||
elif re.match("^date", typname): |
||||
l[attname] = 'date' |
||||
elif re.match("^bool", typname): |
||||
l[attname] = 'bool' |
||||
elif re.match("^float", typname): |
||||
l[attname] = 'decimal' |
||||
elif re.match("^money", typname): |
||||
l[attname] = 'money' |
||||
else: |
||||
l[attname] = 'text' |
||||
|
||||
self.attnames[cl] = l |
||||
return self.attnames[cl] |
||||
|
||||
# return a tuple from a database |
||||
def get(self, cl, arg, keyname = None): |
||||
if keyname == None: # use the primary key by default |
||||
keyname = self.pkeys[cl] |
||||
|
||||
fnames = self.get_attnames(cl) |
||||
|
||||
if type(arg) == type({}): |
||||
# To allow users to work with multiple tables we munge the |
||||
# name when the key is "oid" |
||||
if keyname == 'oid': k = arg['oid_%s' % cl] |
||||
else: k = arg[keyname] |
||||
else: |
||||
k = arg |
||||
arg = {} |
||||
|
||||
# We want the oid for later updates if that isn't the key |
||||
if keyname == 'oid': |
||||
q = "SELECT * FROM %s WHERE oid = %s" % (cl, k) |
||||
else: |
||||
q = "SELECT oid AS oid_%s, %s FROM %s WHERE %s = %s" % \ |
||||
(cl, string.join(fnames.keys(), ','),\ |
||||
cl, keyname, _quote(k, fnames[keyname])) |
||||
|
||||
if self.debug != None: print self.debug % q |
||||
res = self.db.query(q).dictresult() |
||||
if res == []: |
||||
raise error, \ |
||||
"No such record in %s where %s is %s" % \ |
||||
(cl, keyname, _quote(k, fnames[keyname])) |
||||
return None |
||||
|
||||
for k in res[0].keys(): |
||||
arg[k] = res[0][k] |
||||
|
||||
return arg |
||||
|
||||
# Inserts a new tuple into a table |
||||
def insert(self, cl, a): |
||||
fnames = self.get_attnames(cl) |
||||
l = [] |
||||
n = [] |
||||
for f in fnames.keys(): |
||||
if a.has_key(f): |
||||
if a[f] == "": l.append("null") |
||||
else: l.append(_quote(a[f], fnames[f])) |
||||
n.append(f) |
||||
|
||||
try: |
||||
q = "INSERT INTO %s (%s) VALUES (%s)" % \ |
||||
(cl, string.join(n, ','), string.join(l, ',')) |
||||
if self.debug != None: print self.debug % q |
||||
a['oid_%s' % cl] = self.db.query(q) |
||||
except: |
||||
raise error, "Error inserting into %s: %s" % (cl, sys.exc_value) |
||||
|
||||
# reload the dictionary to catch things modified by engine |
||||
return self.get(cl, a, 'oid') |
||||
|
||||
# update always works on the oid which get returns |
||||
def update(self, cl, a): |
||||
q = "SELECT oid FROM %s WHERE oid = %s" % (cl, a['oid_%s' % cl]) |
||||
if self.debug != None: print self.debug % q |
||||
res = self.db.query(q).getresult() |
||||
if len(res) < 1: |
||||
raise error, "No record in %s where oid = %s (%s)" % \ |
||||
(cl, a['oid_%s' % cl], sys.exc_value) |
||||
|
||||
v = [] |
||||
k = 0 |
||||
fnames = self.get_attnames(cl) |
||||
|
||||
for ff in fnames.keys(): |
||||
if a.has_key(ff) and a[ff] != res[0][k]: |
||||
v.append("%s = %s" % (ff, _quote(a[ff], fnames[ff]))) |
||||
|
||||
if v == []: |
||||
return None |
||||
|
||||
try: |
||||
q = "UPDATE %s SET %s WHERE oid = %s" % \ |
||||
(cl, string.join(v, ','), a['oid_%s' % cl]) |
||||
if self.debug != None: print self.debug % q |
||||
self.db.query(q) |
||||
except: |
||||
raise error, "Can't update %s: %s" % (cl, sys.exc_value) |
||||
|
||||
# reload the dictionary to catch things modified by engine |
||||
return self.get(cl, a, 'oid') |
||||
|
||||
# At some point we will need a way to get defaults from a table |
||||
def clear(self, cl, a = {}): |
||||
fnames = self.get_attnames(cl) |
||||
for ff in fnames.keys(): |
||||
if fnames[ff] in ['int', 'decimal', 'seq', 'money']: |
||||
a[ff] = 0 |
||||
elif fnames[ff] == 'date': |
||||
a[ff] = 'TODAY' |
||||
else: |
||||
a[ff] = "" |
||||
|
||||
a['oid'] = 0 |
||||
return a |
||||
|
||||
# Like update, delete works on the oid |
||||
# one day we will be testing that the record to be deleted |
||||
# isn't referenced somewhere (or else PostgreSQL will) |
||||
def delete(self, cl, a): |
||||
try: |
||||
q = "DELETE FROM %s WHERE oid = %s" % (cl, a['oid_%s' % cl]) |
||||
if self.debug != None: print self.debug % q |
||||
self.db.query(q) |
||||
except: |
||||
return "Can't delete %s: %s" % (cl, sys.exc_value) |
||||
|
||||
return None |
||||
|
||||
|
||||
# The rest of these methods are for convenience. Note that X.method() |
||||
# and X.db.method() are equivalent |
||||
def query(self, query): return self.db.query(query) |
||||
def reset(self): self.db.reset() |
||||
def getnotify(self): self.db.getnotify() |
||||
def inserttable(self): self.db.inserttable() |
||||
|
||||
# The following depend on being activated in the underlying C code |
||||
def putline(self): self.db.putline() |
||||
def getline(self): self.db.getline() |
||||
def endcopy(self): self.db.endcopy() |
||||
def locreate(self): self.db.locreate() |
||||
def getlo(self): self.db.getlo() |
||||
def loimport(self): self.db.loimport() |
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@ |
||||
#! /usr/local/bin/python |
||||
# pgtools.py - valuable functions for PostGreSQL tutorial |
||||
# written 1995 by Pascal ANDRE |
||||
|
||||
import sys |
||||
|
||||
# number of rows |
||||
scr_size = 24 |
||||
|
||||
# waits for a key |
||||
def wait_key(): |
||||
print "Press <enter>" |
||||
sys.stdin.read(1) |
||||
|
||||
# displays a table for a select query result |
||||
def display(fields, result): |
||||
print result |
||||
# gets cols width |
||||
fmt = [] |
||||
sep = '+' |
||||
head = '|' |
||||
for i in range(0, len(fields)): |
||||
max = len(fields[i]) |
||||
for j in range(0, len(result)): |
||||
if i < len(result[j]): |
||||
if len(result[j][i]) > max: |
||||
max = len(result[j][i]) |
||||
fmt.append(" %%%ds |" % max) |
||||
for j in range(0, max): |
||||
sep = sep + '-' |
||||
sep = sep + '--+' |
||||
for i in range(0, len(fields)): |
||||
head = head + fmt[i] % fields[i] |
||||
print sep + '\n' + head + '\n' + sep |
||||
pos = 6 |
||||
for i in range(0, len(result)): |
||||
str = '|' |
||||
for j in range(0, len(result[i])): |
||||
str = str + fmt[j] % result[i][j] |
||||
print str |
||||
pos = pos + 1 |
||||
if pos == scr_size: |
||||
print sep |
||||
wait_key() |
||||
print sep + '\n' + head + '\n' + sep |
||||
pos = 6 |
||||
print sep |
||||
wait_key() |
||||
@ -0,0 +1,133 @@ |
||||
# syscat.py - parses some system catalogs |
||||
# inspired from the PostgreSQL tutorial |
||||
# adapted to Python 1995 by Pascal ANDRE |
||||
|
||||
print "____________________________________________________________________" |
||||
print |
||||
print "MODULE SYSCAT.PY : PARSES SOME POSTGRESQL SYSTEM CATALOGS" |
||||
print |
||||
print "This module is designed for being imported from python prompt" |
||||
print |
||||
print "In order to run the samples included here, first create a connection" |
||||
print "using : cnx = syscat.connect(...)" |
||||
print "then start the demo with: syscat.demo(cnx)" |
||||
print |
||||
print "Some results may be empty, depending on your base status." |
||||
print |
||||
print "____________________________________________________________________" |
||||
print |
||||
|
||||
from pgext import * |
||||
from pgtools import * |
||||
|
||||
# lists all simple indices |
||||
def list_simple_ind(pgcnx): |
||||
result = pgcnx.query("select bc.relname " \ |
||||
"as class_name, ic.relname as index_name, a.attname " \ |
||||
"from pg_class bc, pg_class ic, pg_index i, pg_attribute a " \ |
||||
"where i.indrelid = bc.oid and i.indexrelid = bc.oid " \ |
||||
" and i.indkey[0] = a.attnum and a.attrelid = bc.oid " \ |
||||
" and i.indproc = '0'::oid " \ |
||||
"order by class_name, index_name, attname") |
||||
return result |
||||
|
||||
# list all user defined attributes and their type in user-defined classes |
||||
def list_all_attr(pgcnx): |
||||
result = pgcnx.query("select c.relname, a.attname, t.typname " \ |
||||
"from pg_class c, pg_attribute a, pg_type t " \ |
||||
"where c.relkind = 'r' and c.relname !~ '^pg_' " \ |
||||
" and c.relname !~ '^Inv' and a.attnum > 0 " \ |
||||
" and a.attrelid = c.oid and a.atttypid = t.oid " \ |
||||
"order by relname, attname") |
||||
return result |
||||
|
||||
# list all user defined base type |
||||
def list_user_base_type(pgcnx): |
||||
result = pgcnx.query("select u.usename, t.typname " \ |
||||
"from pg_type t, pg_user u " \ |
||||
"where u.usesysid = int2in(int4out(t.typowner)) " \ |
||||
" and t.typrelid = '0'::oid and t.typelem = '0'::oid " \ |
||||
" and u.usename <> 'postgres' order by usename, typname") |
||||
return result |
||||
|
||||
# list all right-unary operators |
||||
def list_right_unary_operator(pgcnx): |
||||
result = pgcnx.query("select o.oprname as right_unary, " \ |
||||
" lt.typname as operand, result.typname as return_type " \ |
||||
"from pg_operator o, pg_type lt, pg_type result " \ |
||||
"where o.oprkind='r' and o.oprleft = lt.oid " \ |
||||
" and o.oprresult = result.oid order by operand") |
||||
return result |
||||
|
||||
# list all left-unary operators |
||||
def list_left_unary_operator(pgcnx): |
||||
result = pgcnx.query("select o.oprname as left_unary, " \ |
||||
" rt.typname as operand, result.typname as return_type " \ |
||||
"from pg_operator o, pg_type rt, pg_type result " \ |
||||
"where o.oprkind='l' and o.oprright = rt.oid " \ |
||||
" and o.oprresult = result.oid order by operand") |
||||
return result |
||||
|
||||
# list all binary operators |
||||
def list_binary_operator(pgcnx): |
||||
result = pgcnx.query("select o.oprname as binary_op, " \ |
||||
" rt.typname as right_opr, lt.typname as left_opr, " \ |
||||
" result.typname as return_type " \ |
||||
"from pg_operator o, pg_type rt, pg_type lt, pg_type result " \ |
||||
"where o.oprkind = 'b' and o.oprright = rt.oid " \ |
||||
" and o.oprleft = lt.oid and o.oprresult = result.oid") |
||||
return result |
||||
|
||||
# returns the name, args and return type from all function of lang l |
||||
def list_lang_func(pgcnx, l): |
||||
result = pgcnx.query("select p.proname, p.pronargs, t.typname " \ |
||||
"from pg_proc p, pg_language l, pg_type t " \ |
||||
"where p.prolang = l.oid and p.prorettype = t.oid " \ |
||||
" and l.lanname = '%s' order by proname" % l) |
||||
return result |
||||
|
||||
# lists all the aggregate functions and the type to which they can be applied |
||||
def list_agg_func(pgcnx): |
||||
result = pgcnx.query("select a.aggname, t.typname " \ |
||||
"from pg_aggregate a, pg_type t " \ |
||||
"where a.aggbasetype = t.oid order by aggname, typname") |
||||
return result |
||||
|
||||
# lists all the operator classes that can be used with each access method as |
||||
# well as the operators that can be used with the respective operator classes |
||||
def list_op_class(pgcnx): |
||||
result = pgcnx.query("select am.amname, opc.opcname, opr.oprname " \ |
||||
"from pg_am am, pg_amop amop, pg_opclass opc, pg_operator opr " \ |
||||
"where amop.amopid = am.oid and amop.amopclaid = opc.oid " \ |
||||
" and amop.amopopr = opr.oid order by amname, opcname, oprname") |
||||
return result |
||||
|
||||
# demo function - runs all examples |
||||
def demo(pgcnx): |
||||
#import sys, os |
||||
#save_stdout = sys.stdout |
||||
#sys.stdout = os.popen("more", "w") |
||||
print "Listing simple indices ..." |
||||
print list_simple_ind(pgcnx) |
||||
print "Listing all attributes ..." |
||||
print list_all_attr(pgcnx) |
||||
print "Listing all user-defined base types ..." |
||||
print list_user_base_type(pgcnx) |
||||
print "Listing all left-unary operators defined ..." |
||||
print list_left_unary_operator(pgcnx) |
||||
print "Listing all right-unary operators defined ..." |
||||
print list_right_unary_operator(pgcnx) |
||||
print "Listing all binary operators ..." |
||||
print list_binary_operator(pgcnx) |
||||
print "Listing C external function linked ..." |
||||
print list_lang_func(pgcnx, 'C') |
||||
print "Listing C internal functions ..." |
||||
print list_lang_func(pgcnx, 'internal') |
||||
print "Listing SQL functions defined ..." |
||||
print list_lang_func(pgcnx, 'sql') |
||||
print "Listing 'aggregate functions' ..." |
||||
print list_agg_func(pgcnx) |
||||
print "Listing 'operator classes' ..." |
||||
print list_op_class(pgcnx) |
||||
#del sys.stdout |
||||
#sys.stdout = save_stdout |
||||
Loading…
Reference in new issue