#!perl -w

# Takes a SQL dump file and wraps all the long lines, emitting another
# SQL dump file.

# Copyright 2015 Ken Takusagawa

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


#14 minutes
use Text::Wrap;
$Text::Wrap::columns=69;  #based on analysis by line-lengths.pl
$Text::Wrap::unexpand=0;
$Text::Wrap::huge='overflow';
&head();
while(<>){
    if(/^INSERT INTO cable \(id, date, refid, classification, origin, destination, header, content\) VALUES /){
        &process($l);
        $l=$_;
    } else {
        $l.=$_;
    }
}
&process($l);
&tail();
print STDERR "count $count bytes $bytes\n";
#&end_doubles();
&end();
sub process {
    my $s=shift;
    $bytes+= length$s;
    return if ($s =~ /^--\n-- PostgreSQL database dump\n--/s);
    $count++;
    my @m;
    die unless (@m = $s =~ /^INSERT INTO cable \(id, date, refid, classification, origin, destination, header, content\) VALUES \((\d+), '(([^']|'')*?)', '(([^']|'')*?)', '(([^']|'')*?)', '(([^']|'')*?)', '(([^']|'')*?)', '(([^']|'')*?)', '(.*)'\);\n(?:$|.*-- PostgreSQL database dump complete)/s);
    my @d;
    push @d,shift@m;
    while(@m){
        push @d,shift@m;
        shift@m;
    };
    die unless @d==8;
    #for(0..$#d){        print "item $_ $d[$_]\n";    } print "\n";
    for$i(2..5){
        die $d[$i] unless &single_line($d[$i]);
    }
    do_work(@d);
};

sub single_line {
    my $s=shift;
    $s =~/^[ -~]*$/;
}
sub multiline1 {
    my $s=shift;
    $s =~/^([ -~]|\x0a)*(.?|$)/;
    if($2 eq '') {
        1;
    } else {
        print "fail $2\n";
        0;
    }
}

sub head {
    print << 'EOF';
--
-- PostgreSQL database dump
--

SET statement_timeout = 0;
SET client_encoding = 'SQL_ASCII';
SET standard_conforming_strings = off;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET escape_string_warning = off;

SET search_path = public, pg_catalog;

SET default_tablespace = '';

SET default_with_oids = false;

--
-- Name: cable; Type: TABLE; Schema: public; Owner: -; Tablespace: 
--

CREATE TABLE cable (
    id integer NOT NULL,
    date timestamp without time zone,
    refid character varying,
    classification character varying,
    origin character varying,
    destination text,
    header text,
    content text
);


--
-- Name: cable_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--

CREATE SEQUENCE cable_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


--
-- Name: cable_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--

ALTER SEQUENCE cable_id_seq OWNED BY cable.id;


--
-- Name: cable_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
--

SELECT pg_catalog.setval('cable_id_seq', 251287, true);


--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--

ALTER TABLE cable ALTER COLUMN id SET DEFAULT nextval('cable_id_seq'::regclass);


--
-- Data for Name: cable; Type: TABLE DATA; Schema: public; Owner: -
--

EOF
}

sub tail {
    print << 'EOF';


--
-- Name: cable_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 
--

ALTER TABLE ONLY cable
    ADD CONSTRAINT cable_pkey PRIMARY KEY (id);


--
-- PostgreSQL database dump complete
--

EOF
}

sub do_work {
    die unless @_==8;
    #&just_print(@_);
    #&line_lengths($_) for(@_);
    $_=&wrap_many($_) for(@_);
    &just_print(@_);
}


sub just_print {
    die unless @_==8;
    print "INSERT INTO cable (id, date, refid, classification, origin, destination, header, content) VALUES ($_[0], '$_[1]', '$_[2]', '$_[3]', '$_[4]', '$_[5]', '";
    multiline_print($_[6]);
    print "', '";
    multiline_print($_[7]);
    print "');\n";
}

sub multiline_print {
    my @F=split /^/,$_[0];
    print for (@F);
}

sub line_lengths {
    my$a=shift;
    $a =~ s/''/'/g;
    $a =~ s/\\\\/\\/g;
    my @F=split /^/,$a;
    for(@F){
        $ls{length$_}++;
    }
}

sub wrap_many {
    my$a=shift;
    $a =~ s/''/'/g;
    $a =~ s/\\\\/\\/g;
    my @F=split /^/,$a;
    my$out="";
    for(@F){
        if(/^\s+$/){
            $out.=$_;
        } else {
            my$item=wrap('','',($_));
            $item .= "\n" if(/\n$/ and $item !~ /\n$/);
            $out .= $item;
        }
    }
    $out =~ s/'/''/g;
    $out =~ s/\\/\\\\/g;
    $out;
}

sub end {
    #&end_line_lengths();
}

sub end_line_lengths {
    for(keys %ls){
        print "$_ $ls{$_}\n";
    }
    print STDERR "done\n";
}
