Index: src/bin/pg_dump/pg_dump.c =================================================================== RCS file: /var/cvsup/pgsql/src/bin/pg_dump/pg_dump.c,v retrieving revision 1.236 diff -c -r1.236 pg_dump.c *** src/bin/pg_dump/pg_dump.c 28 Oct 2001 06:25:58 -0000 1.236 --- src/bin/pg_dump/pg_dump.c 16 Dec 2001 11:27:50 -0000 *************** *** 130,135 **** --- 130,176 ---- bool oids; } DumpContext; + /* char* array utilities implementations -- dbv 20011216 */ + strarray + strarrayInit() + { + strarray _ary = (strarray)malloc(sizeof(strarray)); + _ary->size = 0; + _ary->data = (char**)malloc(sizeof(char*)); + _ary->data[0] = NULL; + return _ary; + } + + void + strarrayFree(strarray _ary) + { + int i = 0; + for(; i <= _ary->size; ++i){ + free(_ary->data[i]); + } + free(_ary); + } + + void + strarrayAdd(strarray _ary, const char* str) + { + _ary->size++; + _ary->data = (char**)realloc(_ary->data,sizeof(char*) * ((_ary->size) + 1)); + _ary->data[_ary->size - 1] = (char*)strdup(str); + _ary->data[_ary->size] = NULL; + } + + int + strarrayContains(strarray _ary, const char* str) + { + int i = 0; + for(; i < _ary->size; ++i) + if( strncmp(str,_ary->data[i],strlen(str)) == 0 ) + return 1; + return 0; + } + /* end of char* utility cruft */ + static void help(const char *progname) { *************** *** 4050,4055 **** --- 4091,4195 ---- } /* + * extract a sequence name from an pg_attrdef.adsrc string . + * This return value must be freed by the caller. + */ + char* + _extractSeqNameFromAdsrc(const char* o_adsrc){ + const char* pre_seq = "nextval('"; + const char* post_seq = "'::text)"; + char* rv = NULL; + if( strlen(o_adsrc) > strlen(pre_seq) + strlen(post_seq) ) + { + int bosn = strlen(pre_seq); + int eosn = strlen(o_adsrc) - strlen(post_seq); + int seqlen = strlen(o_adsrc) - strlen(post_seq) - strlen(pre_seq); + if( strncmp( o_adsrc, pre_seq, strlen(pre_seq) ) == 0 + && strncmp( o_adsrc + eosn, post_seq, strlen(post_seq)) == 0) + { + /* strip off any containing '"' chars. These will /always/ exist + * for SERIAL-sequences, but may not be present for user-created + * sequences on this relation -- dbv 20011216 + */ + int i = 0; + char* rvp; + if( *(o_adsrc + bosn) == '"') + { + ++bosn; + --seqlen; + --seqlen; + } + rv = (char*)malloc(seqlen+1); + rvp = rv; + for(; i < seqlen; ++i) + *rvp++ = *(o_adsrc + bosn + i); + *rvp = '\0'; + } + } + return rv; + } + + /* + * getSerialSequenceNames + * args: + * ary - an initialized strarray to add found sequences to + * relid_str - string representation of relation oid + */ + void + getSerialSequenceNames(strarray ary, const char* relid_str) + { + /* There is no direct relationship between a table and + * a SERIAL-created sequence in the system catalog, so + * we've gotta get the pg_attrdef.adsrc for the default + * and extract the sequence name from the nextval(...) + * function call definition. This is a kludge. + * -- dbv 20011215 + */ + int fnum; + int numtup; + int i; + char** seqs; + int seq_count; + PQExpBuffer query; + PGresult* res; + + seqs = (char**)malloc(sizeof(char*)); + seq_count = 0; + query = createPQExpBuffer(); + appendPQExpBuffer(query, "SELECT adsrc FROM pg_attrdef WHERE adrelid=%s",relid_str); + res = PQexec(g_conn,query->data); + + if( !res || PQresultStatus(res) != PGRES_TUPLES_OK){ + write_msg(NULL, "query to lookup SERIAL-create sequences for relation '%s' failed: %s", + relid_str, + PQerrorMessage(g_conn)); + exit_nicely(); + } + + numtup = PQntuples(res); + if( numtup <= 0 ){ + /* no SERIAL-created sequences on this relation */ + PQclear(res); + destroyPQExpBuffer(query); + return; + } + + fnum = PQfnumber(res,"adsrc"); + for( i = 0; i < numtup; ++i ){ + char* sn = _extractSeqNameFromAdsrc(PQgetvalue(res,i,fnum)); + if( sn ){ + strarrayAdd(ary,sn); + } + free(sn); /* malloc'd above and strdup'd in strarrayAdd */ + } + + PQclear(res); + destroyPQExpBuffer(query); + + return; + } + + /* * dumpTables: * write out to fout all the user-define tables */ *************** *** 4067,4098 **** k; PQExpBuffer q = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); - char *serialSeq = NULL; /* implicit sequence name created - * by SERIAL datatype */ - const char *serialSeqSuffix = "_id_seq"; /* suffix for implicit - * SERIAL sequences */ char **parentRels; /* list of names of parent relations */ int numParents; int actual_atts; /* number of attrs in this CREATE statment */ char *reltypename; char *objoid; const char *((*commentDeps)[]); /* First - dump SEQUENCEs */ if (tablename && strlen(tablename) > 0) { ! /* XXX this code only works for serial columns named "id" */ ! /* We really need dependency analysis! */ ! serialSeq = malloc(strlen(tablename) + strlen(serialSeqSuffix) + 1); ! strcpy(serialSeq, tablename); ! strcat(serialSeq, serialSeqSuffix); } for (i = 0; i < numTables; i++) { if (!(tblinfo[i].sequence)) continue; if (!tablename || (!strcmp(tblinfo[i].relname, tablename)) ! || (serialSeq && !strcmp(tblinfo[i].relname, serialSeq))) { /* becomeUser(fout, tblinfo[i].usename); */ dumpSequence(fout, tblinfo[i], schemaOnly, dataOnly); --- 4207,4239 ---- k; PQExpBuffer q = createPQExpBuffer(); PQExpBuffer delq = createPQExpBuffer(); char **parentRels; /* list of names of parent relations */ int numParents; int actual_atts; /* number of attrs in this CREATE statment */ char *reltypename; char *objoid; const char *((*commentDeps)[]); + strarray serialSeqs; /* string array containing names of sequences on tablename */ + + serialSeqs = strarrayInit(); /* First - dump SEQUENCEs */ if (tablename && strlen(tablename) > 0) { ! for (i = 0; i < numTables; i++){ ! if( tblinfo[i].sequence ) /* is a sequence */ ! continue; ! /* TODO: check for wildcard table match */ ! if ( strcmp(tblinfo[i].relname, tablename) == 0 ) ! getSerialSequenceNames(serialSeqs, tblinfo[i].oid); ! } } for (i = 0; i < numTables; i++) { if (!(tblinfo[i].sequence)) continue; if (!tablename || (!strcmp(tblinfo[i].relname, tablename)) ! || strarrayContains(serialSeqs,tblinfo[i].relname)) { /* becomeUser(fout, tblinfo[i].usename); */ dumpSequence(fout, tblinfo[i], schemaOnly, dataOnly); *************** *** 4100,4107 **** dumpACL(fout, tblinfo[i]); } } ! if (serialSeq) ! free(serialSeq); for (i = 0; i < numTables; i++) { --- 4241,4247 ---- dumpACL(fout, tblinfo[i]); } } ! strarrayFree(serialSeqs); for (i = 0; i < numTables; i++) { Index: src/bin/pg_dump/pg_dump.h =================================================================== RCS file: /var/cvsup/pgsql/src/bin/pg_dump/pg_dump.h,v retrieving revision 1.76 diff -c -r1.76 pg_dump.h *** src/bin/pg_dump/pg_dump.h 5 Nov 2001 17:46:30 -0000 1.76 --- src/bin/pg_dump/pg_dump.h 16 Dec 2001 11:28:04 -0000 *************** *** 280,283 **** --- 280,299 ---- extern const char *fmtId(const char *identifier, bool force_quotes); extern void exit_nicely(void); + /* char* array utilities -- dbv 20011216 */ + struct strarray { + int size; /* number of char* in the strarray. */ + char** data; + }; + typedef struct strarray* strarray; + + strarray strarrayInit(void); + void strarrayFree(strarray _ary); + void strarrayAdd(strarray _ary, const char* str); + int strarrayContains(strarray _ary, const char* str); + + /* get strarray of sequences on a given relation oid */ + void getSerialSequenceNames(strarray, const char*); + char* _extractSeqNameFromAdsrc(const char*); + #endif /* PG_DUMP_H */