diff options
-rw-r--r-- | psql/help-psql.pd | 81 | ||||
-rw-r--r-- | psql/psql.c | 170 |
2 files changed, 126 insertions, 125 deletions
diff --git a/psql/help-psql.pd b/psql/help-psql.pd index e4e60b4..4810926 100644 --- a/psql/help-psql.pd +++ b/psql/help-psql.pd @@ -1,50 +1,53 @@ -#N canvas 36 70 917 494 10; -#X obj 377 470 print postgres; -#X msg 36 186 sql DROP DATABASE pddbase sqlend; -#X msg 79 87 sql CREATE DATABASE pddbase sqlend; -#X text 69 44 1 Create a new database - by first; -#X text 86 61 connecting to PostgreSQL's default database: 'template1' +#N canvas 241 93 917 646 10; +#X obj 377 547 print postgres; +#X msg 27 171 sql DROP DATABASE pddbase sqlend; +#X msg 8 105 sql CREATE DATABASE pddbase sqlend; +#X text 374 63 to the newly created 'pddbase' database; +#X text 375 52 2 Create a new table in the database - this time connecting ; -#X text 479 56 to the newly created 'pddbase' database; -#X text 461 40 2 Create a new table in the database - this time connecting +#X text 419 141 3 Insert some data. Each click of the message below ; -#X text 467 114 3 Insert some data. Each click of the message below -; -#X text 484 132 inserts a new row into the specified table.; -#X text 471 228 4 Retrieve all data in the specified table using a +#X text 418 151 inserts a new row into the specified table.; +#X text 450 271 4 Retrieve all data in the specified table using a wild; -#X text 32 208 click this to destroy the database; -#X msg 456 79 sql CREATE TABLE datatable(id INTEGER \, duration FLOAT +#X text 27 155 click this to destroy the database; +#X msg 377 95 sql CREATE TABLE datatable(id INTEGER \, duration FLOAT \, type VARCHAR \, datetime DATETIME) sqlend; -#X text 487 242 card '*'. Note each row returned is preceded by an +#X text 451 282 card '*'. Note each row returned is preceded by an index; -#X text 484 300 Also show the degree of error; -#X msg 466 318 sql SELECT id \, ABS((duration - 1500)/1500) AS error +#X text 463 358 Also show the degree of error; +#X msg 459 376 sql SELECT id \, ABS((duration - 1500)/1500) AS error FROM datatable ORDER BY error LIMIT 1 sqlend; -#X text 470 288 5 Find the 'id' of entry closest to 1500 msec in duration. +#X text 463 346 5 Find the 'id' of entry closest to 1500 msec in duration. ; -#X msg 466 150 sql INSERT INTO datatable VALUES(22 \, 1023.33 \, 'singing' +#X msg 418 177 sql INSERT INTO datatable VALUES(22 \, 1023.33 \, 'singing' \, datetime('now'::date \, 'now'::time)) sqlend \, sql INSERT INTO datatable VALUES(24 \, 1500.1 \, 'coughing' \, datetime('now'::date \, 'now'::time)) sqlend \, sql INSERT INTO datatable VALUES(26 \, 2222.11 \, 'sobbing' \, datetime('now'::date \, 'now'::time)) sqlend; -#X text 56 350 example of sqlsingle specifying; -#X text 57 366 host machine and port; -#X text 9 9 sqlsingle. Follow the numbered steps; -#X obj 500 393 route 0 1 2 3 4 5 6 7 8; -#X text 649 392 use route to separate indexed 'tuples'; -#X obj 500 428 unpack 0 0 s s; -#X text 596 428 use unpack to access individual fields; -#X msg 470 262 sql select * from datatable WHERE id < 30 sqlend; -#X obj 96 137 psql template1; -#X obj 57 330 psql pddbase localhost 5432; -#X obj 377 365 psql pddbase; -#X connect 1 0 25 0; -#X connect 2 0 25 0; -#X connect 11 0 27 0; -#X connect 14 0 27 0; -#X connect 16 0 27 0; -#X connect 20 0 22 0; -#X connect 24 0 27 0; -#X connect 27 0 20 0; -#X connect 27 0 0 0; +#X obj 475 549 route 0 1 2 3 4 5 6 7 8; +#X text 624 548 use route to separate indexed 'tuples'; +#X obj 475 584 unpack 0 0 s s; +#X text 571 584 use unpack to access individual fields; +#X msg 449 305 sql select * from datatable WHERE id < 30 sqlend; +#X obj 377 446 psql pddbase; +#X obj 8 222 psql template1 localhost 5432; +#X obj 446 479 bng 15 250 50 0 empty empty empty 0 -6 0 10 -262144 +-1 -1; +#X text 472 480 Bang when the results from each query have been returned +; +#X text 7 56 1 Create a new database - by connecting; +#X text 7 69 to PostgreSQL's default database: 'template1'; +#X obj 8 4 cnv 15 250 40 empty empty [psql] 20 12 1 14 -191407 -66577 +0; +#X text 27 24 based on [sqlsingle] by Iain Mott; +#X connect 1 0 21 0; +#X connect 2 0 21 0; +#X connect 9 0 20 0; +#X connect 12 0 20 0; +#X connect 14 0 20 0; +#X connect 15 0 17 0; +#X connect 19 0 20 0; +#X connect 20 0 15 0; +#X connect 20 0 0 0; +#X connect 20 1 22 0; diff --git a/psql/psql.c b/psql/psql.c index 5fac954..d02b5a3 100644 --- a/psql/psql.c +++ b/psql/psql.c @@ -32,7 +32,7 @@ #include <stdlib.h> #include "libpq-fe.h" -#define MAXSQLFIELDS 10 +#define MAXSQLFIELDS 20 /* postgres datatypes and corresponding 'Oid's */ @@ -43,11 +43,11 @@ #define PGDATETIME 1184 #define PGVARCHAR 1043 -typedef struct psql -{ +typedef struct psql{ + t_object t_ob; - t_outlet *x_outlet1; - t_outlet *x_outlet2; + t_outlet *x_outlet1, + *x_outlet2; t_atom get_atom; t_symbol *x_sym; char sqlStringStore[MAXPDSTRING]; @@ -58,18 +58,13 @@ typedef struct psql *dbName; char port[20]; PGconn *conn; - t_int connected; -} t_psql; + t_int connected, + in_query; -static void psql_float(t_psql *x, t_floatarg f) -{ - post("psql: %f", f); -} +} t_psql; +static void psql_SQL (t_psql *x, t_symbol *s){ -static void psql_SQL (t_psql *x, t_symbol *s) -{ - /* post("psql_SQL called");*/ char sqlString[MAXPDSTRING]; int argc = 10; t_atom argv[argc]; @@ -78,8 +73,8 @@ static void psql_SQL (t_psql *x, t_symbol *s) int starttime_fnum; int endtime_fnum; int spurtorder_fnum; - int nFields; - int i, j; + int nFields; + int i, j; t_symbol *t_sym; PGresult *res; int tupplecount; @@ -101,9 +96,11 @@ static void psql_SQL (t_psql *x, t_symbol *s) x->connected = 1; res = PQexec(x->conn, x->sqlStringStore); - if (PQresultStatus(res) != PGRES_TUPLES_OK && PQresultStatus(res) != PGRES_COMMAND_OK) + if (PQresultStatus(res) != PGRES_TUPLES_OK && PQresultStatus(res) != + PGRES_COMMAND_OK) { - fprintf(stderr, "psql: Action failed. PQresultStatus is %s\n", PQresStatus(PQresultStatus(res))); + fprintf(stderr, "psql: Action failed. PQresultStatus is %s\n", + PQresStatus(PQresultStatus(res))); } else { @@ -121,9 +118,9 @@ static void psql_SQL (t_psql *x, t_symbol *s) starttime_fnum = PQfnumber(res, "starttime"); endtime_fnum = PQfnumber(res, "endtime"); spurtorder_fnum = PQfnumber(res, "spurtorder"); + /* fetch the instances */ - for (i = 0; i < PQntuples(res); i++) - { + for (i = 0; i < PQntuples(res); i++) { /* merge field of a query instance into a list */ SETFLOAT(&argv[0], i); for (j=0; j<nFields; j++) @@ -142,13 +139,15 @@ static void psql_SQL (t_psql *x, t_symbol *s) else { t_sym = gensym( PQgetvalue(res, i, j)); SETSYMBOL(&argv[j+1], t_sym); - post("Undefined PG data type. OID: %d. Stored in list as Symbol", fType); + post( + "Undefined PG data type. OID: %d. Stored in list as Symbol", fType); } } t_sym = gensym( "A_FLOAT"); outlet_list(x->x_outlet1, t_sym, nFields+1, argv); } + outlet_bang(x->x_outlet2); PQclear(res); } } @@ -161,20 +160,18 @@ static void psql_close(t_psql *x){ x->connected = 0; } -static void psql_anything(t_psql *x, t_symbol *s, int ac, t_atom *av, t_floatarg f) -{ +static void psql_anything(t_psql *x, t_symbol *s, int ac, t_atom *av, t_floatarg f){ char sqlString[MAXPDSTRING]; int i; char buf[MAXPDSTRING]; char mybuf[MAXPDSTRING]; - /*post("Calling psql_anything");*/ - - if(!strcmp(s->s_name,"close")) + if(!strcmp(s->s_name,"close") && !x->in_query) psql_close(x); else{ - if (strcmp(s->s_name, "sql") != 0) - { + if (strcmp(s->s_name, "sql")){ + + strcat(x->sqlStringStore, ", "); /* replace the truncated first symbol */ @@ -182,28 +179,29 @@ static void psql_anything(t_psql *x, t_symbol *s, int ac, t_atom *av, t_floatarg strcat(x->sqlStringStore, s->s_name); strcat(x->sqlStringStore, " "); - /* see if it ends OK */ - + /* see if it ends OK */ atom_string(av+ac-1, buf, MAXPDSTRING); - if (strcmp(buf, "sqlend") == 0) - { + if (!strcmp(buf, "sqlend")){ + int tc = ac-1; - for (i = 0; i < tc; i++) - { + for (i = 0; i < tc; i++){ + atom_string(av+i, buf, MAXPDSTRING); strcat(x->sqlStringStore, buf); if (i < tc - 1) strcat(x->sqlStringStore, " "); + } - /*post("executing query");*/ psql_SQL (x, s); + + x->in_query = 0; + } - else - { + else { for (i = 0; i < ac; i++) { atom_string(av+i, buf, MAXPDSTRING); @@ -211,16 +209,18 @@ static void psql_anything(t_psql *x, t_symbol *s, int ac, t_atom *av, t_floatarg if (i < ac - 1) strcat(x->sqlStringStore, " "); } - } } else { - /* if s->s_name DOES equal "sql" - first clear sqlStringStore then check if end of string terminates with "sqlend" */ + /* if s->s_name DOES equal "sql" - first clear sqlStringStore then check + * if end of string terminates with "sqlend" */ + + x->in_query = 1; strcpy(x->sqlStringStore, ""); atom_string(av+ac-1, buf, MAXPDSTRING); - if (strcmp(buf, "sqlend") != 0) + if (strcmp(buf, "sqlend")) { for (i = 0; i < ac; i++) { @@ -241,12 +241,10 @@ static void psql_anything(t_psql *x, t_symbol *s, int ac, t_atom *av, t_floatarg if (i < ac - 1) strcat(x->sqlStringStore, " "); } - /*post("executing query");*/ psql_SQL (x, s); - } - - + x->in_query = 0; + } } atom_string(av+ac-1, buf, MAXPDSTRING); @@ -259,28 +257,29 @@ static void psql_list(t_psql *x, t_symbol *s, int ac, t_atom *av) { int i; char buf[MAXPDSTRING]; - /* post("list"); */ + strcat(x->sqlStringStore, ","); - if (strcmp(x->sqlStringStore, "") != 0) - { + if (strcmp(x->sqlStringStore, "")){ atom_string(av+ac-1, buf, MAXPDSTRING); - if (strcmp(buf, "sqlend") == 0) - { + if (strcmp(buf, "sqlend") == 0){ + ac = ac -1; - for (i = 0; i < ac; i++) - { + + for (i = 0; i < ac; i++){ strcat(x->sqlStringStore, " "); atom_string(av+i, buf, MAXPDSTRING); strcat(x->sqlStringStore, buf); } + + x->in_query = 0; + } - else - { - for (i = 0; i < ac; i++) - { + else{ + + for (i = 0; i < ac; i++){ strcat(x->sqlStringStore, " "); atom_string(av+i, buf, MAXPDSTRING); strcat(x->sqlStringStore, buf); @@ -293,7 +292,6 @@ static void psql_list(t_psql *x, t_symbol *s, int ac, t_atom *av) } - t_class *psql_class; static void *psql_new(t_symbol *s, int argc, t_atom *argv) @@ -301,52 +299,56 @@ static void *psql_new(t_symbol *s, int argc, t_atom *argv) t_psql *x = (t_psql *)pd_new(psql_class); x->x_sym = gensym("psql"); x->x_outlet1 = outlet_new(&x->t_ob, &s_list); + x->x_outlet2 = outlet_new(&x->t_ob, &s_bang); + + x->in_query = 0; + if(argc == 0) { - x->pghost = NULL; /* host name of the backend server */ - x->pgport = NULL; /* port of the backend server */ - x->pgoptions = NULL; /* special options to start up the backend server */ - x->pgtty = NULL; /* debugging tty for the backend server */ + x->pghost = NULL; /* host name of the backend server */ + x->pgport = NULL; /* port of the backend server */ + x->pgoptions = NULL; /* special options to start up the backend server */ + x->pgtty = NULL; /* debugging tty for the backend server */ x->dbName = "template1"; post("using dbase template1 on local UNIX socket"); } else if(argc == 1 && argv[0].a_type == A_SYMBOL) { - x->pghost = NULL; /* host name of the backend server */ - x->pgport = NULL; /* port of the backend server */ - x->pgoptions = NULL; /* special options to start up the backend server */ - x->pgtty = NULL; /* debugging tty for the backend server */ + x->pghost = NULL; /* host name of the backend server */ + x->pgport = NULL; /* port of the backend server */ + x->pgoptions = NULL; /* special options to start up the backend server */ + x->pgtty = NULL; /* debugging tty for the backend server */ x->dbName = argv[0].a_w.w_symbol->s_name; - /* post("using %s on localhost", argv[0].a_w.w_symbol->s_name); */ } else if(argc == 3 && argv[0].a_type == A_SYMBOL && argv[1].a_type == A_SYMBOL && argv[2].a_type == A_FLOAT) { - x->pghost = argv[1].a_w.w_symbol->s_name; /* host name of the backend server */ + x->pghost = argv[1].a_w.w_symbol->s_name; /* host name of the backend server */ sprintf(x->port, "%d", (int)argv[2].a_w.w_float); - x->pgport = x->port; /* port of the backend server */ - // strncpy(x->pgport, tmp); /* port of the backend server */ - x->pgoptions = NULL; /* special options to start up the backend server */ - x->pgtty = NULL; /* debugging tty for the backend server */ + x->pgport = x->port; /* port of the backend server */ + // strncpy(x->pgport, tmp); /* port of the backend server */ + x->pgoptions = NULL; /* special options to start up the backend server */ + x->pgtty = NULL; /* debugging tty for the backend server */ x->dbName = argv[0].a_w.w_symbol->s_name; - /* post("using dbase %s on %s and port %s", x->dbName, x->pghost, x->pgport); */ } else { - x->pghost = NULL; /* host name of the backend server */ - x->pgport = NULL; /* port of the backend server */ - x->pgoptions = NULL; /* special options to start up the backend server */ - x->pgtty = NULL; /* debugging tty for the backend server */ + x->pghost = NULL; /* host name of the backend server */ + x->pgport = NULL; /* port of the backend server */ + x->pgoptions = NULL; /* special options to start up the backend server */ + x->pgtty = NULL; /* debugging tty for the backend server */ x->dbName = "template1"; post("psql: invalid arguments using default template1 dbase on localhost"); } - // check postmaster is running on specified port and machine by attempting to x->connect to template1 + /* check postmaster is running on specified port and machine by attempting to + * x->connect to template1 */ x->conn = PQsetdb(x->pghost, x->pgport, x->pgoptions, x->pgtty, "template1"); if (PQstatus(x->conn) == CONNECTION_BAD) { - fprintf(stderr, "psql: Connection to template1 failed. Perhaps the postmaster is not running on the specified port and machine \n"); + fprintf(stderr, + "psql: Connection to template1 failed. Perhaps the postmaster is not running on the specified port and machine \n"); fprintf(stderr, "psql: Connect error is: %s", PQerrorMessage(x->conn)); } else @@ -354,18 +356,14 @@ static void *psql_new(t_symbol *s, int argc, t_atom *argv) return (x); } - static void psql_free(t_psql *x){ - if(x->connected) - psql_close(x); - } +static void psql_free(t_psql *x){ + if(x->connected) + psql_close(x); +} -void psql_setup(void) -{ - /* post("psql_setup"); */ +void psql_setup(void) { psql_class = class_new(gensym("psql"), (t_newmethod)psql_new, (t_method)psql_free, sizeof(t_psql), 0, A_GIMME, 0); class_addanything(psql_class, psql_anything); class_addlist(psql_class, psql_list); } - - |