mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 10:30:33 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			308 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			308 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* -------------------------------------------------------------------------
 | |
|  * pg_dumplo
 | |
|  *
 | |
|  * $PostgreSQL: pgsql/contrib/pg_dumplo/main.c,v 1.22 2004/11/28 23:49:49 tgl Exp $
 | |
|  *
 | |
|  *					Karel Zak 1999-2000
 | |
|  * -------------------------------------------------------------------------
 | |
|  */
 | |
| 
 | |
| #include "postgres_fe.h"
 | |
| 
 | |
| #include <errno.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| #include "libpq-fe.h"
 | |
| #include "libpq/libpq-fs.h"
 | |
| 
 | |
| #include "pg_dumplo.h"
 | |
| 
 | |
| #ifndef HAVE_STRDUP
 | |
| #include "strdup.h"
 | |
| #endif
 | |
| 
 | |
| #include "getopt_long.h"
 | |
| 
 | |
| #ifndef HAVE_INT_OPTRESET
 | |
| int			optreset;
 | |
| #endif
 | |
| 
 | |
| char	   *progname = NULL;
 | |
| 
 | |
| int			main(int argc, char **argv);
 | |
| static void usage(void);
 | |
| static void parse_lolist(LODumpMaster * pgLO);
 | |
| 
 | |
| 
 | |
| /*-----
 | |
|  *	The mother of all C functions
 | |
|  *-----
 | |
|  */
 | |
| int
 | |
| main(int argc, char **argv)
 | |
| {
 | |
| 	LODumpMaster _pgLO,
 | |
| 			   *pgLO = &_pgLO;
 | |
| 	char	   *pwd = NULL;
 | |
| 
 | |
| 	pgLO->argv = argv;
 | |
| 	pgLO->argc = argc;
 | |
| 	pgLO->action = 0;
 | |
| 	pgLO->lolist = NULL;
 | |
| 	pgLO->user = NULL;
 | |
| 	pgLO->db = NULL;
 | |
| 	pgLO->host = NULL;
 | |
| 	pgLO->port = NULL;
 | |
| 	pgLO->space = NULL;
 | |
| 	pgLO->index = NULL;
 | |
| 	pgLO->remove = FALSE;
 | |
| 	pgLO->quiet = FALSE;
 | |
| 	pgLO->counter = 0;
 | |
| 	pgLO->lolist_start = 0;
 | |
| 
 | |
| 	progname = argv[0];
 | |
| 
 | |
| 	/*
 | |
| 	 * Parse ARGV
 | |
| 	 */
 | |
| 	if (argc > 1)
 | |
| 	{
 | |
| 		int			arg;
 | |
| 		extern int	optind;
 | |
| 		int			l_index = 0;
 | |
| 		static struct option l_opt[] = {
 | |
| 			{"help", no_argument, 0, 'h'},
 | |
| 			{"user", required_argument, 0, 'u'},
 | |
| 			{"pwd", required_argument, 0, 'p'},
 | |
| 			{"db", required_argument, 0, 'd'},
 | |
| 			{"host", required_argument, 0, 'h'},
 | |
| 			{"port", required_argument, 0, 'o'},
 | |
| 			{"space", required_argument, 0, 's'},
 | |
| 			{"import", no_argument, 0, 'i'},
 | |
| 			{"export", no_argument, 0, 'e'},
 | |
| 			{"remove", no_argument, 0, 'r'},
 | |
| 			{"quiet", no_argument, 0, 'q'},
 | |
| 			{"all", no_argument, 0, 'a'},
 | |
| 			{"show", no_argument, 0, 'w'},
 | |
| 			{NULL, 0, 0, 0}
 | |
| 		};
 | |
| 
 | |
| 		while ((arg = getopt_long(argc, argv, "?aeho:u:p:qd:l:t:irs:w", l_opt, &l_index)) != -1)
 | |
| 		{
 | |
| 			switch (arg)
 | |
| 			{
 | |
| 				case '?':
 | |
| 				case 'h':
 | |
| 					usage();
 | |
| 					exit(RE_OK);
 | |
| 				case 'u':
 | |
| 					pgLO->user = strdup(optarg);
 | |
| 					break;
 | |
| 				case 't':
 | |
| 					pgLO->host = strdup(optarg);
 | |
| 					break;
 | |
| 				case 'o':
 | |
| 					pgLO->port = strdup(optarg);
 | |
| 					break;
 | |
| 				case 'p':
 | |
| 					pwd = strdup(optarg);
 | |
| 					break;
 | |
| 				case 'd':
 | |
| 					pgLO->db = strdup(optarg);
 | |
| 					break;
 | |
| 				case 's':
 | |
| 					pgLO->space = strdup(optarg);
 | |
| 					break;
 | |
| 				case 'i':
 | |
| 					pgLO->action = ACTION_IMPORT;
 | |
| 					break;
 | |
| 				case 'l':
 | |
| 					pgLO->action = ACTION_EXPORT_ATTR;
 | |
| 					pgLO->lolist_start = optind - 1;
 | |
| 					parse_lolist(pgLO);
 | |
| 					break;
 | |
| 				case 'e':
 | |
| 				case 'a':
 | |
| 					pgLO->action = ACTION_EXPORT_ALL;
 | |
| 					break;
 | |
| 				case 'w':
 | |
| 					pgLO->action = ACTION_SHOW;
 | |
| 					break;
 | |
| 				case 'r':
 | |
| 					pgLO->remove = TRUE;
 | |
| 					break;
 | |
| 				case 'q':
 | |
| 					pgLO->quiet = TRUE;
 | |
| 					break;
 | |
| 				default:
 | |
| 					fprintf(stderr, "%s: bad arg -%c\n", progname, arg);
 | |
| 					usage();
 | |
| 					exit(RE_ERROR);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		usage();
 | |
| 		exit(RE_ERROR);
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Check space
 | |
| 	 */
 | |
| 	if (pgLO->space==NULL && pgLO->action != ACTION_SHOW)
 | |
| 	{
 | |
| 		if (!(pgLO->space = getenv("PWD")))
 | |
| 			pgLO->space = ".";
 | |
| 	}
 | |
| 
 | |
| 	if (!pgLO->action)
 | |
| 	{
 | |
| 		fprintf(stderr, "%s: What do you want - export or import?\n", progname);
 | |
| 		exit(RE_ERROR);
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Make connection
 | |
| 	 */
 | |
| 	pgLO->conn = PQsetdbLogin(pgLO->host, pgLO->port, NULL, NULL, pgLO->db,
 | |
| 							  pgLO->user, pwd);
 | |
| 
 | |
| 	if (PQstatus(pgLO->conn) == CONNECTION_BAD)
 | |
| 	{
 | |
| 		fprintf(stderr, "%s (connection): %s\n", progname, PQerrorMessage(pgLO->conn));
 | |
| 		exit(RE_ERROR);
 | |
| 	}
 | |
| 	pgLO->host = PQhost(pgLO->conn) ? PQhost(pgLO->conn) : "localhost";
 | |
| 	pgLO->db = PQdb(pgLO->conn);
 | |
| 	pgLO->user = PQuser(pgLO->conn);
 | |
| 
 | |
| 
 | |
| 	/*
 | |
| 	 * Init index file
 | |
| 	 */
 | |
| 	if (pgLO->action != ACTION_SHOW)
 | |
| 		index_file(pgLO);
 | |
| 
 | |
| 	PQexec(pgLO->conn, "SET search_path = public");
 | |
| 
 | |
| 	PQexec(pgLO->conn, "BEGIN");
 | |
| 
 | |
| 	switch (pgLO->action)
 | |
| 	{
 | |
| 
 | |
| 		case ACTION_SHOW:
 | |
| 		case ACTION_EXPORT_ALL:
 | |
| 			load_lolist(pgLO);
 | |
| 			/* FALL THROUGH */
 | |
| 
 | |
| 		case ACTION_EXPORT_ATTR:
 | |
| 			pglo_export(pgLO);
 | |
| 			if (!pgLO->quiet)
 | |
| 			{
 | |
| 				if (pgLO->action == ACTION_SHOW)
 | |
| 					printf("\nDatabase '%s' contains %d large objects.\n\n", pgLO->db, pgLO->counter);
 | |
| 				else
 | |
| 					printf("\nExported %d large objects.\n\n", pgLO->counter);
 | |
| 			}
 | |
| 			break;
 | |
| 
 | |
| 		case ACTION_IMPORT:
 | |
| 			pglo_import(pgLO);
 | |
| 			if (!pgLO->quiet)
 | |
| 				printf("\nImported %d large objects.\n\n", pgLO->counter);
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	PQexec(pgLO->conn, "COMMIT");
 | |
| 	PQfinish(pgLO->conn);
 | |
| 
 | |
| 	if (pgLO->action != ACTION_SHOW)
 | |
| 		fclose(pgLO->index);
 | |
| 
 | |
| 	exit(RE_OK);
 | |
| }
 | |
| 
 | |
| static void
 | |
| parse_lolist(LODumpMaster * pgLO)
 | |
| {
 | |
| 	LOlist	   *ll;
 | |
| 	char	  **d, *loc, *loc2, 
 | |
| 		  buff[MAX_SCHEMA_NAME + MAX_TABLE_NAME + MAX_ATTR_NAME + 3];
 | |
| 
 | |
| 	pgLO->lolist = (LOlist *) malloc(pgLO->argc * sizeof(LOlist));
 | |
| 
 | |
| 	if (!pgLO->lolist)
 | |
| 	{
 | |
| 		fprintf(stderr, "%s: can't allocate memory\n", progname);
 | |
| 		exit(RE_ERROR);
 | |
| 	}
 | |
| 
 | |
| 	for (d = pgLO->argv + pgLO->lolist_start, ll = pgLO->lolist;
 | |
| 		 *d != NULL;
 | |
| 		 d++, ll++)
 | |
| 	{
 | |
| 
 | |
| 		strncpy(buff, *d, MAX_SCHEMA_NAME + MAX_TABLE_NAME + MAX_ATTR_NAME + 2);
 | |
| 
 | |
| 		if ((loc = strchr(buff, '.')) == NULL || *(loc+1)=='\0')
 | |
| 		{
 | |
| 			fprintf(stderr, "%s: '%s' is bad 'table.attr' or 'schema.table.attr'\n", progname, buff);
 | |
| 			exit(RE_ERROR);
 | |
| 		}
 | |
| 		loc2 = strchr(loc+1, '.');
 | |
| 		*loc = '\0';
 | |
| 		
 | |
| 		if (loc2)
 | |
| 		{
 | |
| 			/* "schema.table.attr" 
 | |
| 			 */
 | |
| 			*loc2 = '\0';
 | |
| 			ll->lo_schema = strdup(buff);
 | |
| 			ll->lo_table = strdup(loc+1);
 | |
| 			ll->lo_attr = strdup(loc2+1);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			ll->lo_schema = strdup("public");
 | |
| 			ll->lo_table = strdup(buff);
 | |
| 			ll->lo_attr = strdup(loc+1);
 | |
| 		}
 | |
| 	}
 | |
| 	ll++;
 | |
| 	ll->lo_table = ll->lo_attr = (char *) NULL;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| usage(void)
 | |
| {
 | |
| 	printf("\npg_dumplo %s - PostgreSQL large objects dump\n", PG_VERSION);
 | |
| 	puts("pg_dumplo [option]\n\n"
 | |
| 		 "-h --help                    this help\n"
 | |
| 	   "-u --user=<username>         username for connection to server\n"
 | |
| 	   "-p --password=<password>     password for connection to server\n"
 | |
| 		 "-d --db=<database>           database name\n"
 | |
| 		 "-t --host=<hostname>         server hostname\n"
 | |
| 	"-o --port=<port>             database server port (default: 5432)\n"
 | |
| 		 "-s --space=<dir>             directory with dump tree (for export/import)\n"
 | |
| 		 "-i --import                  import large obj dump tree to DB\n"
 | |
| 	"-e --export                  export (dump) large obj to dump tree\n"
 | |
| 		"-l <schema.table.attr ...>   dump attribute (columns) with LO to dump tree\n"
 | |
| 		 "-a --all                     dump all LO in DB (default)\n"
 | |
| 		 "-r --remove                  if is set '-i' try remove old LO\n"
 | |
| 		 "-q --quiet                   run quietly\n"
 | |
| 		 "-w --show                    not dump, but show all LO in DB\n"
 | |
| 		 "\n"
 | |
| 		 "Example (dump):   pg_dumplo -d my_db -s /my_dump/dir -l t1.a t1.b t2.a\n"
 | |
| 		 "                  pg_dumplo -a -d my_db -s /my_dump/dir\n"
 | |
| 		 "Example (import): pg_dumplo -i -d my_db -s /my_dump/dir\n"
 | |
| 		 "Example (show):   pg_dumplo -w -d my_db\n\n"
 | |
| 		 "Note:  * option '-l' must be last option!\n"
 | |
| 		 "       * default schema is \"public\"\n"
 | |
|   		 "       * option '-i' without option '-r' make new large obj in DB\n"
 | |
| 		 "         not rewrite old, the '-i' UPDATE oid numbers in table.attr only!\n"
 | |
| 		 "       * if option -s is not set, pg_dumplo uses $PWD or \".\"\n"
 | |
| 		);						/* puts() */
 | |
| }
 |