1
0
mirror of https://gitlab.com/depesz/explain.depesz.com.git synced 2025-07-05 00:58:52 +02:00

Added title for plan

Nathan Thom requested ability to add title to plan.

It wasn't very complicated, so it's added :)
This commit is contained in:
Hubert depesz Lubaczewski
2011-06-28 15:25:14 +02:00
parent 986148627e
commit a5fc1f2544
5 changed files with 216 additions and 68 deletions

View File

@ -26,6 +26,11 @@ sub index {
# anonymization # anonymization
my $is_anon = $self->req->param( 'is_anon' ) ? 1 : 0; my $is_anon = $self->req->param( 'is_anon' ) ? 1 : 0;
# plan title
my $title = $self->req->param( 'title' );
$title = '' unless defined $title;
$title = '' if 'Optional title' eq $title;
# try # try
eval { eval {
@ -54,10 +59,12 @@ sub index {
eval { eval {
# send mail # send mail
$self->send_mail( { $self->send_mail(
{
subject => q|Can't create explain from...|, subject => q|Can't create explain from...|,
msg => $plan msg => $plan
} ); }
);
}; };
# leave... # leave...
@ -65,7 +72,7 @@ sub index {
} }
# save to database # save to database
my $id = $self->database->save_with_random_name( $plan, $is_public, $is_anon, ); my $id = $self->database->save_with_random_name( $title, $plan, $is_public, $is_anon, );
# redirect to /show/:id # redirect to /show/:id
return $self->redirect_to( 'show', id => $id ); return $self->redirect_to( 'show', id => $id );
@ -75,14 +82,13 @@ sub show {
my $self = shift; my $self = shift;
# value of "/:id" param # value of "/:id" param
my $id = defined $self->stash->{ id } my $id = defined $self->stash->{ id } ? $self->stash->{ id } : '';
? $self->stash->{ id } : '';
# missing or invalid # missing or invalid
return $self->redirect_to( 'new-explain' ) unless $id =~ m{\A[a-zA-Z0-9]+\z}; return $self->redirect_to( 'new-explain' ) unless $id =~ m{\A[a-zA-Z0-9]+\z};
# get plan source from database # get plan source from database
my $plan = $self->database->get_plan( $id ); my ( $plan, $title ) = $self->database->get_plan( $id );
# not found in database # not found in database
return $self->redirect_to( 'new-explain', status => 404 ) unless $plan; return $self->redirect_to( 'new-explain', status => 404 ) unless $plan;
@ -105,8 +111,9 @@ sub show {
return $self->redirect_to( 'new-explain' ); return $self->redirect_to( 'new-explain' );
} }
# put explain to stash # put explain and title to stash
$self->stash->{ explain } = $explain; $self->stash->{ explain } = $explain;
$self->stash->{ title } = $title;
# render will be called automatically # render will be called automatically
return; return;
@ -138,19 +145,18 @@ sub contact {
unless Email::Valid->address( $self->req->param( 'email' ) || '' ); unless Email::Valid->address( $self->req->param( 'email' ) || '' );
# send # send
$self->send_mail( { $self->send_mail(
{
msg => sprintf( msg => sprintf(
"\nMessage from: %s <%s>" . "\nMessage from: %s <%s>" . "\nPosted from: %s with %s" . "\n****************************************\n\n" . "%s",
"\nPosted from: %s with %s" .
"\n****************************************\n\n" .
"%s",
$self->req->param( 'name' ) || '', $self->req->param( 'name' ) || '',
$self->req->param( 'email' ), $self->req->param( 'email' ),
$self->tx->remote_address, $self->tx->remote_address,
$self->req->headers->user_agent, $self->req->headers->user_agent,
$self->req->param( 'message' ) $self->req->param( 'message' )
) )
} ); }
);
# mail sent message # mail sent message
$self->flash( message => 'Mail sent' ); $self->flash( message => 'Mail sent' );
@ -160,6 +166,7 @@ sub contact {
} }
sub help { sub help {
# direct to template # direct to template
return ( shift )->render; return ( shift )->render;
} }

View File

@ -66,13 +66,13 @@ sub register {
} }
sub save_with_random_name { sub save_with_random_name {
my ( $self, $content, $is_public, $is_anon ) = @_; my ( $self, $title, $content, $is_public, $is_anon ) = @_;
# create statement handler # create statement handler
my $sth = $self->dbh->prepare( 'SELECT register_plan(?, ?, ?)' ); my $sth = $self->dbh->prepare( 'SELECT register_plan(?, ?, ?, ?)' );
# execute # execute
$sth->execute( $content, $is_public, $is_anon ); $sth->execute( $title, $content, $is_public, $is_anon );
# register_plan returns plan id # register_plan returns plan id
my @row = $sth->fetchrow_array; my @row = $sth->fetchrow_array;
@ -90,7 +90,7 @@ sub get_plan {
my ( $self, $plan_id ) = @_; my ( $self, $plan_id ) = @_;
# create statement handler # create statement handler
my $sth = $self->dbh->prepare( 'SELECT plan FROM plans WHERE id = ?' ); my $sth = $self->dbh->prepare( 'SELECT plan, title FROM plans WHERE id = ?' );
# execute # execute
$sth->execute( $plan_id ); $sth->execute( $plan_id );
@ -102,7 +102,7 @@ sub get_plan {
$sth->finish; $sth->finish;
# return plan # return plan
return $row[ 0 ]; return @row;
} }
sub get_public_list { sub get_public_list {

201
sql/create.sql Executable file → Normal file
View File

@ -1,32 +1,36 @@
\connect template1 postgres --
-- PostgreSQL database dump
--
\set ON_ERROR_STOP OFF SET statement_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
DROP DATABASE "explain"; --
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
--
DROP USER "explain"; CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
\set ON_ERROR_STOP ON
CREATE USER "explain" WITH password 'explain'; --
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
--
CREATE DATABASE "explain" WITH encoding 'utf8' owner "explain"; COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
\connect "explain" postgres
CREATE procedural LANGUAGE plpgsql; SET search_path = public, pg_catalog;
\connect "explain" "explain" --
-- Name: get_random_string(integer); Type: FUNCTION; Schema: public; Owner: -
--
-- plan CREATE FUNCTION get_random_string(string_length integer) RETURNS text
CREATE TABLE plans ( LANGUAGE plpgsql
id TEXT PRIMARY KEY, AS $$
plan TEXT NOT NULL,
entered_on timestamptz NOT NULL DEFAULT now( ),
is_public bool NOT NULL DEFAULT 'true'
);
CREATE OR REPLACE FUNCTION get_random_string( string_length INT4 ) RETURNS TEXT AS $$
DECLARE DECLARE
possible_chars TEXT = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; possible_chars TEXT = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
output TEXT = ''; output TEXT = '';
@ -34,34 +38,167 @@ DECLARE
pos INT4; pos INT4;
BEGIN BEGIN
FOR i IN 1..string_length LOOP FOR i IN 1..string_length LOOP
pos := 1 + cast( random( ) * ( length( possible_chars ) - 1 ) AS INT4 ); pos := 1 + cast( random() * ( length(possible_chars) - 1) as INT4 );
output := output || substr(possible_chars, pos, 1); output := output || substr(possible_chars, pos, 1);
END LOOP; END LOOP;
RETURN output; RETURN output;
END; END;
$$ LANGUAGE plpgsql; $$;
CREATE OR REPLACE FUNCTION register_plan( in_plan TEXT, in_is_public BOOL ) RETURNS TEXT AS $$
--
-- Name: register_plan(text, boolean); Type: FUNCTION; Schema: public; Owner: -
--
CREATE FUNCTION register_plan(in_plan text, in_is_public boolean) RETURNS text
LANGUAGE plpgsql
AS $$
DECLARE DECLARE
use_hash_length INT4 := 2; use_hash_length int4 := 2;
use_hash TEXT; use_hash text;
BEGIN BEGIN
LOOP LOOP
use_hash := get_random_string(use_hash_length); use_hash := get_random_string(use_hash_length);
BEGIN BEGIN
INSERT INTO plans ( id, plan, is_public, entered_on ) VALUES ( use_hash, in_plan, in_is_public, now( ) ); INSERT INTO plans (id, plan, is_public, entered_on) values (use_hash, in_plan, in_is_public, now());
RETURN use_hash; RETURN use_hash;
EXCEPTION when unique_violation THEN EXCEPTION WHEN unique_violation THEN
-- do nothing -- do nothing
END; END;
use_hash_length := use_hash_length + 1; use_hash_length := use_hash_length + 1;
IF use_hash_length >= 30 THEN IF use_hash_length >= 30 THEN
raise EXCEPTION 'Random string of length == 30 requested. Something is wrong.'; raise exception 'Random string of length == 30 requested. something''s wrong.';
END IF; END IF;
END LOOP; END LOOP;
END; END;
$$ LANGUAGE plpgsql; $$;
--
-- Name: register_plan(text, boolean, boolean); Type: FUNCTION; Schema: public; Owner: -
--
CREATE FUNCTION register_plan(in_plan text, in_is_public boolean, in_is_anonymized boolean) RETURNS text
LANGUAGE plpgsql
AS $$
DECLARE
use_hash_length int4 := 2;
use_hash text;
BEGIN
LOOP
use_hash := get_random_string(use_hash_length);
BEGIN
INSERT INTO plans (id, plan, is_public, entered_on, is_anonymized) values (use_hash, in_plan, in_is_public, now(), in_is_anonymized);
RETURN use_hash;
EXCEPTION WHEN unique_violation THEN
-- do nothing
END;
use_hash_length := use_hash_length + 1;
IF use_hash_length >= 30 THEN
raise exception 'Random string of length == 30 requested. something''s wrong.';
END IF;
END LOOP;
END;
$$;
--
-- Name: register_plan(text, text, boolean, boolean); Type: FUNCTION; Schema: public; Owner: -
--
CREATE FUNCTION register_plan(in_title text, in_plan text, in_is_public boolean, in_is_anonymized boolean) RETURNS text
LANGUAGE plpgsql
AS $$
DECLARE
use_hash_length int4 := 2;
use_hash text;
BEGIN
LOOP
use_hash := get_random_string(use_hash_length);
BEGIN
INSERT INTO plans (id, title, plan, is_public, entered_on, is_anonymized) values (use_hash, in_title, in_plan, in_is_public, now(), in_is_anonymized);
RETURN use_hash;
EXCEPTION WHEN unique_violation THEN
-- do nothing
END;
use_hash_length := use_hash_length + 1;
IF use_hash_length >= 30 THEN
raise exception 'Random string of length == 30 requested. something''s wrong.';
END IF;
END LOOP;
END;
$$;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: another; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE another (
i integer
);
--
-- Name: plans; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE plans (
id text NOT NULL,
plan text NOT NULL,
entered_on timestamp with time zone DEFAULT now() NOT NULL,
is_public boolean DEFAULT true NOT NULL,
is_anonymized boolean DEFAULT false NOT NULL,
title text
);
--
-- Name: z; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE z (
i integer NOT NULL,
j integer NOT NULL
);
--
-- Name: plans_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
ALTER TABLE ONLY plans
ADD CONSTRAINT plans_pkey PRIMARY KEY (id);
--
-- Name: z_i_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
ALTER TABLE ONLY z
ADD CONSTRAINT z_i_key UNIQUE (i);
--
-- Name: z_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
ALTER TABLE ONLY z
ADD CONSTRAINT z_pkey PRIMARY KEY (j, i);
--
-- Name: r; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
CREATE UNIQUE INDEX r ON z USING btree (j);
--
-- PostgreSQL database dump complete
--

View File

@ -15,6 +15,8 @@
<form id="new-explain" method="post" action="<%= url_for 'current' %>"> <form id="new-explain" method="post" action="<%= url_for 'current' %>">
<div class="fe fe-first fe_plan"> <div class="fe fe-first fe_plan">
<label for="title">Optional title for plan:</label>
<input id="title" name="title" class="auto-hint" title="Optional title"/>
<label for="plan">Paste your explain/explain analyze here:</label> <label for="plan">Paste your explain/explain analyze here:</label>
<textarea id="plan" name="plan" class="auto-hint" title="For example: <textarea id="plan" name="plan" class="auto-hint" title="For example:
QUERY PLAN QUERY PLAN

View File

@ -1,7 +1,9 @@
% layout 'default'; % layout 'default';
% my $title = stash( 'id' ); % my $id = stash( 'id' );
% title $title; % my $title = stash( 'title' );
% my $full_title = $title ? "$id : $title" : $id;
% title $full_title;
%# c = e|i|x|m (colorize = exclusive|inclusive|rows-x|mixed) %# c = e|i|x|m (colorize = exclusive|inclusive|rows-x|mixed)
@ -122,10 +124,10 @@
<tr class="n <%= $row_class %>" data-node_id="<%= $node_id =%>" data-node_parent="<%= $parent =%>" data-level="<%= $level =%>" data-e="<%= $exclusive_point =%>" data-i="<%= $inclusive_point =%>" data-x="<%= $rows_x_point =%>"> <tr class="n <%= $row_class %>" data-node_id="<%= $node_id =%>" data-node_parent="<%= $parent =%>" data-level="<%= $level =%>" data-e="<%= $exclusive_point =%>" data-i="<%= $inclusive_point =%>" data-x="<%= $rows_x_point =%>">
<td class="e c-<%= $exclusive_point =%><%= $cfg->{ ve } ? '' : ' tight' %>"> <td class="e c-<%= $exclusive_point =%><%= $cfg->{ ve } ? '' : ' tight' %>">
<span><%= sprintf '%.3f', $node->total_exclusive_time =%></span> <span><%= sprintf '%.3f', defined $node->total_exclusive_time ? $node->total_exclusive_time : 0 =%></span>
</td> </td>
<td class="i c-<%= $inclusive_point =%><%= $cfg->{ vi } ? '' : ' tight' %>"> <td class="i c-<%= $inclusive_point =%><%= $cfg->{ vi } ? '' : ' tight' %>">
<span><%= sprintf '%.3f', $node->total_inclusive_time =%></span> <span><%= sprintf '%.3f', defined $node->total_inclusive_time ? $node->total_inclusive_time : 0 =%></span>
</td> </td>
<td class="x c-<%= $rows_x_point =%><%= $cfg->{ vx } ? '' : ' tight' %>"> <td class="x c-<%= $rows_x_point =%><%= $cfg->{ vx } ? '' : ' tight' %>">
<span> <span>
@ -270,7 +272,7 @@
% end; % end;
<h1>Result: <%= $title %></h1> <h1>Result: <%= $full_title %></h1>
<div class="explain-form"> <div class="explain-form">