1 /*Copyright (c) Brian B.
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Lesser General Public
5 License as published by the Free Software Foundation; either
6 version 3 of the License, or (at your option) any later version.
7 See the file LICENSE included with this distribution for more
10 #include "pgsql_cmd.h"
12 void show (pgconn_t
*conn
, char **line
, size_t *line_len
) {
13 strptr_t tok
= { .ptr
= NULL
, .len
= 0 };
14 strntok(line
, line_len
, CONST_STR_LEN(STR_SPACES
), &tok
);
15 if (-1 == strntok(line
, line_len
, CONST_STR_LEN(STR_SPACES
), &tok
))
17 if (0 == cmpstr(tok
.ptr
, tok
.len
, CONST_STR_LEN("table")))
18 show_table(conn
, line
, line_len
);
19 else if (0 == cmpstr(tok
.ptr
, tok
.len
, CONST_STR_LEN("tables")))
23 cstr_t
*get_current_schema (pgconn_t
*conn
) {
24 pg_execsql(conn
, CONST_STR_LEN("select current_schema()"));
25 return pg_getstr(conn
, 0, 0);
28 cstr_t
*get_dbsize (pgconn_t
*conn
, char *dbname
) {
29 str_t
*sql
= strprintf("SELECT pg_size_pretty(pg_database_size('%s'))", dbname
);
30 pg_execsql(conn
, sql
->ptr
, sql
->len
);
31 cstr_t
*res
= pg_getstr(conn
, 0, 0);
36 cstr_t
*get_tablesize (pgconn_t
*conn
, char *schema
, char *table
) {
37 str_t
*sql
= strprintf("SELECT pg_size_pretty(pg_total_relation_size('%s.%s'))",
39 pg_execsql(conn
, sql
->ptr
, sql
->len
);
40 cstr_t
*res
= pg_getstr(conn
, 0, 0);
45 cstr_t
*get_tablerecs (pgconn_t
*conn
, char *schema
, char *table
) {
46 str_t
*sql
= strprintf("SELECT count(*) from %s.%s",
48 pg_execsql(conn
, sql
->ptr
, sql
->len
);
49 cstr_t
*res
= pg_getstr(conn
, 0, 0);
54 static int *get_max_lens (pgconn_t
*conn
) {
55 int *max_lens
= calloc(pg_nrecs(conn
), sizeof(int));
57 for (int i
= 0; i
< pg_nrecs(conn
); ++i
)
58 for (int j
= 0; j
< pg_nflds(conn
); ++j
)
59 if (!pg_isnull(conn
, i
, j
) && pg_fldlen(conn
, i
, j
) > max_lens
[j
])
60 max_lens
[j
] = pg_fldlen(conn
, i
, j
);
62 for (int i
= 0; i
< pg_nflds(conn
); ++i
) {
63 int l
= strlen(conn
->rowdesc
->fields
[i
].fname
);
64 if (l
> max_lens
[i
]) max_lens
[i
] = l
;
70 static void print_field_names (pgconn_t
*conn
, int *max_lens
) {
72 for (int i
= 0; i
< pg_nflds(conn
); ++i
) {
73 const char *fldnam
= conn
->rowdesc
->fields
[i
].fname
;
74 cstr_t
*s
= mkcstrpad(fldnam
, strlen(fldnam
), ' ', max_lens
[i
]);
75 max_len
+= max_lens
[i
];
76 for (int j
= 0; j
< s
->len
; ++j
)
77 s
->ptr
[j
] = toupper(s
->ptr
[j
]);
79 printf("|%s|", s
->ptr
);
81 printf("%s|", s
->ptr
);
84 cstr_t
*s
= mkcstrfill(max_len
+pg_nflds(conn
), '-');
85 printf("\n%s\n", s
->ptr
);
89 void print_result (pgconn_t
*conn
) {
90 int *max_lens
= get_max_lens(conn
);
92 print_field_names(conn
, max_lens
);
93 for (int i
= 0; i
< pg_nrecs(conn
); ++i
) {
94 for (int j
= 0; j
< pg_nflds(conn
); ++j
) {
96 if (pg_isnull(conn
, i
, j
))
97 str
= mkcstrfill(max_lens
[j
], ' ');
99 strptr_t s
= pg_get(conn
, i
, j
);
100 str
= mkcstrpad(s
.ptr
, s
.len
, ' ', max_lens
[j
]);
103 printf("|%s|", str
->ptr
);
105 printf("%s|", str
->ptr
);
118 DECLARE_LIST(tables
,table_t
)
119 DECLARE_LIST_FUN(tables
,table_t
)
126 static void clear_table (table_t
*t
) {
127 if (t
->name
) free(t
->name
);
128 if (t
->size
) free(t
->size
);
131 static void print_table_field (cstr_t
*val
, int max_len
) {
134 s
= mkcstrpad(val
->ptr
, val
->len
, ' ', max_len
);
136 s
= mkcstrfill(max_len
, ' ');
137 printf("|%s", s
->ptr
);
141 static void print_table_size (pgconn_t
*conn
, cstr_t
*table_name
) {
142 str_t
*sql
= strprintf("select count(*) from %s", table_name
->ptr
);
144 if (0 == pg_execsql(conn
, sql
->ptr
, sql
->len
))
145 s
= pg_getstr(conn
, 0, 0);
146 if (s
) printf("|%s\n", s
->ptr
); else printf("|0\n");
151 static int print_table (table_t
*t
, void *userdata
) {
152 stmt_info_t
*si
= userdata
;
154 print_table_field(t
->name
, si
->max_lens
[0]);
155 print_table_field(t
->size
, si
->max_lens
[1]);
156 print_table_size(si
->conn
, t
->name
);
158 return ENUM_CONTINUE
;
161 static size_t print_header_col (const char *name
, size_t name_len
, int len
) {
163 cstr_t
*s
= mkcstrpad(name
, name_len
, ' ', len
);
164 printf("|%s", s
->ptr
);
170 static void print_tables_header (int *max_lens
) {
171 size_t n
= print_header_col(CONST_STR_LEN("NAME"), max_lens
[0]);
172 n
+= print_header_col(CONST_STR_LEN("SIZE"), max_lens
[1]);
173 n
+= print_header_col(CONST_STR_LEN("RECORDS"), max_lens
[2]);
174 cstr_t
*s
= mkcstrfill(n
+ 3, '-');
175 printf("\n%s\n", s
->ptr
);
180 "select distinct i.table_name," \
181 " pg_size_pretty(pg_total_relation_size(i.table_schema || '.' || i.table_name)) " \
182 "from information_schema.tables i, pg_catalog.pg_tables p " \
183 "where i.table_schema = p.schemaname" \
184 " and tableowner <> 'postgres'" \
185 " and table_type = 'BASE TABLE'" \
186 " and i.table_schema = current_schema()"
187 void show_tables (pgconn_t
*conn
) {
188 pg_execsql(conn
, CONST_STR_LEN(SQL_TABLES
));
190 if (!pg_nrecs(conn
)) {
196 .max_lens
= get_max_lens(conn
),
199 tables_t
*tables
= create_tables(CF_UNDEFINED
, CF_UNDEFINED
, CF_UNDEFINED
);
201 tables
->on_free
= clear_table
;
202 for (int i
= 0; i
< pg_nrecs(conn
); ++i
) {
204 .name
= pg_getstr(conn
, i
, 0),
205 .size
= pg_getstr(conn
, i
, 1)
207 add_tables(&tables
, &item
, CF_TAIL
);
211 print_tables_header(si
.max_lens
);
212 foreach_tables(tables
, print_table
, &si
, 0);
214 free_tables(&tables
);
219 "select ordinal_position, column_name, case is_nullable when 'YES' then '' else 'not null' end case, data_type, character_maximum_length " \
220 "from information_schema.columns " \
221 "where table_schema = '%s' and table_name = '%s'"
222 void show_table (pgconn_t
*conn
, char **line
, size_t *line_len
) {
224 strptr_t tok
= { .ptr
= NULL
, .len
= 0 };
225 cstr_t
*schema
, *table
;
228 if (-1 == strntok(line
, line_len
, CONST_STR_LEN(STR_SPACES
), &tok
))
230 e
= tok
.ptr
+ tok
.len
;
231 if ((p
= strnchr(tok
.ptr
, '.', tok
.len
))) {
232 schema
= mkcstr(tok
.ptr
, (uintptr_t)p
- (uintptr_t)tok
.ptr
);
233 table
= mkcstr(p
+1, (uintptr_t)e
- (uintptr_t)p
-1);
235 schema
= get_current_schema(conn
);
236 table
= mkcstr(tok
.ptr
, tok
.len
);
239 sql
= strprintf(SQL_TABLE
, schema
->ptr
, table
->ptr
);
240 if (!pg_execsql(conn
, sql
->ptr
, sql
->len
)) {
249 cstr_t
*table_size
= get_tablesize(conn
, schema
->ptr
, table
->ptr
),
250 *table_nrecs
= get_tablerecs(conn
, schema
->ptr
, table
->ptr
);
251 printf("Table size: %s; Records: %s\n", table_size
->ptr
, table_nrecs
->ptr
);