Document usage of PGSQL. Bug#1486
[asterisk/asterisk.git] / apps / app_sql_postgres.c
index 628987a..0aac680 100755 (executable)
@@ -5,7 +5,7 @@
  * 
  * Copyright (C) 2002, Christos Ricudis
  *
- * Christos Ricudis <ricudis@paiko.gr>
+ * Christos Ricudis <ricudis@itc.auth.gr>
  *
  * This program is free software, distributed under the terms of
  * the GNU General Public License
@@ -39,57 +39,67 @@ static char *app = "PGSQL";
 static char *synopsis = "Do several SQLy things";
 
 static char *descrip = 
-"  PGSQL():  Do several SQLy things\n";
+"PGSQL():  Do several SQLy things\n"
+"Syntax:\n"
+"  PGSQL(Connect var option-string)\n"
+"    Connects to a database.  Option string contains standard PostgreSQL\n"
+"    parameters like host=, dbname=, user=.  Connection identifer returned\n"
+"    in ${var}\n"
+"  PGSQL(Query var ${connection_identifier} query-string)\n"
+"    Executes standard SQL query contained in query-string using established\n"
+"    connection identified by ${connection_identifier}. Reseult of query is\n"
+"    is stored in ${var}.\n"
+"  PGSQL(Fetch statusvar ${result_identifier} var1 var2 ... varn)\n"
+"    Fetches a single row from a result set contained in ${result_identifier}.\n"
+"    Assigns returned fields to ${var1} ... ${varn}.  ${statusvar} is set TRUE\n"
+"    if additional rows exist in reseult set.\n"
+"  PGSQL(Clear ${result_identifier})\n"
+"    Frees memory and datastructures associated with result set.\n" 
+"  PGSQL(Disconnect ${connection_identifier})\n"
+"    Disconnects from named connection to PostgreSQL.\n" ;
 
 /*
 
 Syntax of SQL commands : 
 
-       Connect #var option-string
+       Connect var option-string
        
        Connects to a database using the option-string and stores the 
-       connection identifier in $var
+       connection identifier in ${var}
        
        
-       Query var connection-identifier query-string
+       Query var ${connection_identifier} query-string
        
        Submits query-string to database backend and stores the result
        identifier in ${var}
        
        
-       Fetch statusvar result-identifier var1 var2 var3 ... varn
+       Fetch statusvar ${result_identifier} var1 var2 var3 ... varn
        
        Fetches a row from the query and stores end-of-table status in 
        ${statusvar} and columns in ${var1}..${varn}
        
        
-       Clear result-identifier
+       Clear ${result_identifier}
 
-       Clears data structures associated with result-identifier
+       Clears data structures associated with ${result_identifier}
        
        
-       Disconnect connection-identifier
+       Disconnect ${connection_identifier}
        
        Disconnects from named connection
        
        
 EXAMPLES OF USE : 
 
-(
- $2 = Connection Identifier
- $3 = Result Identifier
- $4 = Fetch Status Identifier (0 = no more rows)
- $5, $6 = Data variables
-)
-
-exten => s,2,PGSQL,"Connect connid host=localhost user=asterisk dbname=credit";
-exten => s,3,PGSQL,"Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${callerid}";
-exten => s,4,PGSQL,"Fetch fetchid ${resultid} datavar1 datavar2";
-exten => s,5,GotoIf,"${fetchid}=1?s|6:s|8";
-exten => s,6,blablabla ${datavar1} ${datavar2} (does blablabla, datavar1 = username, datavar2 = credit);
-exten => s,7,Goto,s|4
-exten => s,8,PGSQL,"Clear ${resultid}";
-exten => s,9,PGSQL,"Disconnect ${connid}";
+exten => s,2,PGSQL(Connect connid host=localhost user=asterisk dbname=credit)
+exten => s,3,PGSQL(Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${CALLERIDNUM})
+exten => s,4,PGSQL(Fetch fetchid ${resultid} datavar1 datavar2)
+exten => s,5,GotoIf(${fetchid}?6:8)
+exten => s,6,Festival("User ${datavar1} currently has credit balance of ${datavar2} dollars.") 
+exten => s,7,Goto(s,4)
+exten => s,8,PGSQL(Clear ${resultid})
+exten => s,9,PGSQL(Disconnect ${connid})
 
 */
 
@@ -201,7 +211,6 @@ static int del_identifier(int identifier,int identifier_type) {
 
 static int aPGSQL_connect(struct ast_channel *chan, void *data) {
        
-       char *ptrptr;
        char *s1,*s4;
        char s[100];
        char *optionstring;
@@ -210,15 +219,17 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
        int res;
        PGconn *karoto;
        int id;
+       char *stringp=NULL;
         
        
        res=0;
        l=strlen(data)+2;
        s1=malloc(l);
        strncpy(s1,data,l);
-       strtok_r(s1," ",&ptrptr); // eat the first token, we already know it :P 
-       var=strtok_r(NULL," ",&ptrptr);
-       optionstring=strtok_r(NULL,"\n",&ptrptr);
+       stringp=s1;
+       strsep(&stringp," "); // eat the first token, we already know it :P 
+       var=strsep(&stringp," ");
+       optionstring=strsep(&stringp,"\n");
                
        karoto = PQconnectdb(optionstring);
         if (PQstatus(karoto) == CONNECTION_BAD) {
@@ -239,7 +250,6 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
 
 static int aPGSQL_query(struct ast_channel *chan, void *data) {
        
-       char *ptrptr;
        char *s1,*s2,*s3,*s4,*s5;
        char s[100];
        char *querystring;
@@ -249,6 +259,7 @@ static int aPGSQL_query(struct ast_channel *chan, void *data) {
        PGconn *karoto;
        PGresult *PGSQLres;
        int id,id1;
+       char *stringp=NULL;
         
        
        res=0;
@@ -256,13 +267,14 @@ static int aPGSQL_query(struct ast_channel *chan, void *data) {
        s1=malloc(l);
        s2=malloc(l);
        strcpy(s1,data);
-       strtok_r(s1," ",&ptrptr); // eat the first token, we already know it :P 
-       s3=strtok_r(NULL," ",&ptrptr);
+       stringp=s1;
+       strsep(&stringp," "); // eat the first token, we already know it :P 
+       s3=strsep(&stringp," ");
        while (1) {     // ugly trick to make branches with break;
                var=s3;
-               s4=strtok_r(NULL," ",&ptrptr);
+               s4=strsep(&stringp," ");
                id=atoi(s4);
-               querystring=strtok_r(NULL,"\n",&ptrptr);
+               querystring=strsep(&stringp,"\n");
                if ((karoto=find_identifier(id,AST_PGSQL_ID_CONNID))==NULL) {
                        ast_log(LOG_WARNING,"Invalid connection identifier %d passed in aPGSQL_query\n",id);
                        res=-1;
@@ -297,7 +309,6 @@ static int aPGSQL_query(struct ast_channel *chan, void *data) {
 
 static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
        
-       char *ptrptr;
        char *s1,*s2,*s3,*s4,*s5,*s6,*s7;
        char s[100];
        char *var;
@@ -309,6 +320,7 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
        int nres;
         struct ast_var_t *variables;
         struct varshead *headp;
+       char *stringp=NULL;
         
         headp=&chan->varshead;
        
@@ -318,8 +330,9 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
        s1=malloc(l);
        s2=malloc(l);
        strcpy(s1,data);
-       strtok_r(s1," ",&ptrptr); // eat the first token, we already know it :P 
-       s3=strtok_r(NULL," ",&ptrptr);
+       stringp=s1;
+       strsep(&stringp," "); // eat the first token, we already know it :P 
+       s3=strsep(&stringp," ");
        while (1) {     // ugly trick to make branches with break;
                var=s3; // fetchid
                fnd=0;
@@ -337,7 +350,7 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
                        pbx_builtin_setvar_helper(chan,s3,s7);
                }
 
-               s4=strtok_r(NULL," ",&ptrptr);
+               s4=strsep(&stringp," ");
                id=atoi(s4); // resultid
                if ((PGSQLres=find_identifier(id,AST_PGSQL_ID_RESID))==NULL) {
                        ast_log(LOG_WARNING,"Invalid result identifier %d passed in aPGSQL_fetch\n",id);
@@ -355,7 +368,7 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
                nres=PQnfields(PGSQLres); 
                ast_log(LOG_WARNING,"ast_PGSQL_fetch : nres = %d i = %d ;\n",nres,i);
                for (j=0;j<nres;j++) {
-                       s5=strtok_r(NULL," ",&ptrptr);
+                       s5=strsep(&stringp," ");
                        if (s5==NULL) {
                                ast_log(LOG_WARNING,"ast_PGSQL_fetch : More tuples (%d) than variables (%d)\n",nres,j);
                                break;
@@ -391,18 +404,19 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
 
 static int aPGSQL_reset(struct ast_channel *chan, void *data) {
        
-       char *ptrptr;
        char *s1,*s3;
        int l;
        PGconn *karoto;
        int id;
+       char *stringp=NULL;
         
        
        l=strlen(data)+2;
        s1=malloc(l);
        strcpy(s1,data);
-       strtok_r(s1," ",&ptrptr); // eat the first token, we already know it :P 
-       s3=strtok_r(NULL," ",&ptrptr);
+       stringp=s1;
+       strsep(&stringp," "); // eat the first token, we already know it :P 
+       s3=strsep(&stringp," ");
        id=atoi(s3);
        if ((karoto=find_identifier(id,AST_PGSQL_ID_CONNID))==NULL) {
                ast_log(LOG_WARNING,"Invalid connection identifier %d passed in aPGSQL_reset\n",id);
@@ -416,18 +430,19 @@ static int aPGSQL_reset(struct ast_channel *chan, void *data) {
 
 static int aPGSQL_clear(struct ast_channel *chan, void *data) {
        
-       char *ptrptr;
        char *s1,*s3;
        int l;
        PGresult *karoto;
        int id;
+       char *stringp=NULL;
         
        
        l=strlen(data)+2;
        s1=malloc(l);
        strcpy(s1,data);
-       strtok_r(s1," ",&ptrptr); // eat the first token, we already know it :P 
-       s3=strtok_r(NULL," ",&ptrptr);
+       stringp=s1;
+       strsep(&stringp," "); // eat the first token, we already know it :P 
+       s3=strsep(&stringp," ");
        id=atoi(s3);
        if ((karoto=find_identifier(id,AST_PGSQL_ID_RESID))==NULL) {
                ast_log(LOG_WARNING,"Invalid result identifier %d passed in aPGSQL_clear\n",id);
@@ -445,18 +460,19 @@ static int aPGSQL_clear(struct ast_channel *chan, void *data) {
        
 static int aPGSQL_disconnect(struct ast_channel *chan, void *data) {
        
-       char *ptrptr;
        char *s1,*s3;
        int l;
        PGconn *karoto;
        int id;
+       char *stringp=NULL;
         
        
        l=strlen(data)+2;
        s1=malloc(l);
        strcpy(s1,data);
-       strtok_r(s1," ",&ptrptr); // eat the first token, we already know it :P 
-       s3=strtok_r(NULL," ",&ptrptr);
+       stringp=s1;
+       strsep(&stringp," "); // eat the first token, we already know it :P 
+       s3=strsep(&stringp," ");
        id=atoi(s3);
        if ((karoto=find_identifier(id,AST_PGSQL_ID_CONNID))==NULL) {
                ast_log(LOG_WARNING,"Invalid connection identifier %d passed in aPGSQL_disconnect\n",id);