diff --git a/pkgs/development/libraries/postgis/default.nix b/pkgs/development/libraries/postgis/default.nix index 41068c4e39a1..016bd23cf1ca 100644 --- a/pkgs/development/libraries/postgis/default.nix +++ b/pkgs/development/libraries/postgis/default.nix @@ -1,51 +1,151 @@ -{stdenv, fetchurl, libxml2, postgresql, geos, proj, perl}: +args@{fetchurl, composableDerivation, stdenv, perl, libxml2, postgresql, geos, proj, flex, ...}: -# TODO: the bin commands to have gtk gui -# compile this optionally ? + /* -# NixOS - usage: services.posgresql.extraPlugins = [ pkgs.postgis ]; + ### NixOS - usage: + ================== -stdenv.mkDerivation { - name = "postgis"; + services.posgresql.extraPlugins = [ pkgs.postgis.v_1_5_1 ]; - src = fetchurl { - url = http://postgis.refractions.net/download/postgis-1.5.1.tar.gz; - sha256 = "0nymvqqi6pp4nh4dcshzqm76x4sraf119jp7l27c2q1lygm6p6jr"; - }; + or if you want to install 1.5.x and 1.3.x at the same time (which works + because the .sql and .so files have different names): - makeFlags = "PERL=${perl}/bin/perl"; + services.postgis.extraPlugins = [ (pkgs.buildEnv { + name = "postgis-plugins"; + ignoreCollisions = 1; # scripts will collide - but there are aliases with version suffixes + paths = [ pkgs.postgis.v_1_3_5 pkgs.postgis.v_1_5_1 ]; + })]; - # default both defaul to postgis location !? - preConfigure = '' - configureFlags="--datadir=$out/share --datarootdir=$out/share --bindir=$out/bin" - makeFlags="PERL=${perl}/bin/perl datadir=$out/share pkglibdir=$out/lib bindir=$out/bin" + By now it is only supported installing one of the 1.3.x verions because + their shared libraries don't differ in naming. - # makeFlags="DESTDIR=$out " - ''; - # create a script enabling postgis features - postInstall = '' - cat >> $out/bin/enable_postgis_for_db << EOF - #!/bin/sh - set -x - t=$out/share/contrib/postgis-1.5 - for db in "\$@"; do - createlang plpgsql \$db - for f in postgis spatial_ref_sys; do - psql -d \$db -f \$t/\$f.sql + + ### important Postgis implementation details: + ============================================= + + Postgis provides a shared library implementing many operations. They are + exposed to the Postgres SQL interpreter by special SQL queries eg: + + CREATE FUNCTION [...] + AS '[..]liblwgeom', 'lwhistogram2d_in' LANGUAGE 'C' IMMUTABLE STRICT; -- WITH (isstrict); + + where liblwgeom is the shared library. + Postgis < 1.5 used absolute paths, in NixOS $libdir is always used. + + Thus if you want to use postgresql dumps which were created by non NixOS + systems you have to adopt the library path. + + + + ### TODO: + ========= + the bin commands to have gtk gui: + */ + + +let + pgDerivationBase = composableDerivation.composableDerivation {} ( fix : + + let version = fix.fixed.version; in { + + name = "postgis-${version}"; + + src = fetchurl { + url = "http://postgis.refractions.net/download/postgis-${fix.fixed.version}.tar.gz"; + inherit (fix.fixed) sha256; + }; + + # don't pass these vars to the builder + removeAttrs = ["hash" "sql_comments" "sql_srcs"]; + + preConfigure = '' + configureFlags="--datadir=$out/share --datarootdir=$out/share --bindir=$out/bin" + makeFlags="PERL=${perl}/bin/perl datadir=$out/share pkglibdir=$out/lib bindir=$out/bin" + ''; + + pg_db_postgis_enable = ./pg_db_postgis_enable.sh; + + scriptNames = [ "pg_db_postgis_enable" ]; # helper scripts + + # prepare fixed parameters for script and create pg_db_postgis_enable script. + # The script just loads postgis features into a list of given databases + postgisEnableScript = '' + s=$out/bin/pg_db_postgis_enable + + sql_comments=$out/share/postgis-${version}/comments.sql + ensureDir $(dirname $sql_comments) + cp $(find -iname ${fix.fixed.sql_comments}) $sql_comments + + for script in $scriptNames; do + tg=$out/bin/$script + substituteAll ''${!script} $tg + chmod +x $tg done - done - EOF - chmod +x $out/bin/enable_postgis_for_db - ''; + ''; - buildInputs = [libxml2 postgresql geos proj perl]; + # create a script enabling postgis features + # also create aliases for all commands adding version information + postInstall = '' + + sql_srcs=$(for sql in ${builtins.toString fix.fixed.sql_srcs}; do echo -n "$(find $out -iname "$sql") "; done ) + + eval "$postgisEnableScript" + eval "$postgisFixLibScript" + + for prog in $out/bin/*; do + ln -s $prog $prog-${version} + done + + cp -r doc $out + ''; + + buildInputs = [libxml2 postgresql geos proj perl]; + + sql_comments = "postgis_comments.sql"; + + meta = { + description = "Geographic Objects for PostgreSQL"; + homepage = "http://postgis.refractions.net"; + license = "GPLv2"; + maintainers = [stdenv.lib.maintainers.marcweber]; + platforms = stdenv.lib.platforms.linux; + }; + }); + + +in rec { + + # these builders just add some custom informaton to the receipe above + + v_1_3_5 = pgDerivationBase.merge ( fix: { + version = "1.3.5"; + buildInputs = [ flex ]; + sha256 = "102d5ybn0db1wrb249dga2v8347vysd4f1brc8zb82d7vdd34wyq"; + sql_srcs = ["lwpostgis.sql" "spatial_ref_sys.sql"]; + + pg_db_postgis_fix_or_load_sql_dump = ./pg_db_postgis_fix_or_load_sql_dump.sh; + libName = "liblwgeom"; + scriptNames = [ "pg_db_postgis_enable" "pg_db_postgis_fix_or_load_sql_dump"]; # helper scripts + + # sql_srcs is defined in postInstall source above + # if store path changes sql should not break. So replace absolute path to + # shared library by path relatve to $libdir known by Postgres. + postInstall = '' + sed -i "s@AS '$out/lib/liblwgeom@AS '\$libdir/liblwgeom@" $sql_srcs $out/share/lwpostgis_upgrade.sql + ''; + }); + + v_1_3_6 = v_1_3_5.merge ({ + version = "1.3.6"; + sha256 = "0i6inyiwc5zgf5a4ssg0y774f8vn45zn5c38ccgnln9r6i54vc6k"; + }); + + v_1_5_1 = pgDerivationBase.merge ( fix : { + version = "1.5.1"; + sha256 = "0nymvqqi6pp4nh4dcshzqm76x4sraf119jp7l27c2q1lygm6p6jr"; + sql_srcs = ["postgis.sql" "spatial_ref_sys.sql"]; + }); - meta = { - description = "Geographic Objects for PostgreSQL"; - homepage = "http://postgis.refractions.net"; - license = "GPLv2"; - maintainers = [stdenv.lib.maintainers.marcweber]; - platforms = stdenv.lib.platforms.linux; - }; } + diff --git a/pkgs/development/libraries/postgis/pg_db_postgis_enable.sh b/pkgs/development/libraries/postgis/pg_db_postgis_enable.sh new file mode 100644 index 000000000000..c7652e20d9f3 --- /dev/null +++ b/pkgs/development/libraries/postgis/pg_db_postgis_enable.sh @@ -0,0 +1,38 @@ +#!/bin/sh +sql_files=(@sql_srcs@) +sql_comments=@sql_comments@ + +do_help(){ echo "$0 [--comments] db_name1 [db_name2 ..]"; } + +for arg in "$@"; do + case "$arg" in + -h|--help) + do_help; exit 0 + ;; + --comments) + LOAD_COMMENTS=1 + ;; + *) + dbs=(${dbs[@]} "$arg") + ;; + esac +done + +PSQL(){ + echo ">> loading $1" + psql -d "$db" -f $1 +} + +for db in ${dbs[@]}; do + createlang plpgsql "$db" + + # mandatory + for sql in $sql_files; do + PSQL $sql + done + + # optionally load some comments + if [ -n "$LOAD_COMMENTS" ]; then + PSQL $sql_comments + fi +done diff --git a/pkgs/development/libraries/postgis/pg_db_postgis_fix_or_load_sql_dump.sh b/pkgs/development/libraries/postgis/pg_db_postgis_fix_or_load_sql_dump.sh new file mode 100644 index 000000000000..6a98c5d24ca8 --- /dev/null +++ b/pkgs/development/libraries/postgis/pg_db_postgis_fix_or_load_sql_dump.sh @@ -0,0 +1,52 @@ +#!/bin/sh +libName=@libName@ + +# this is a quick and dirty implementation + +do_help(){ + echo "$0 --str str in-file|- [out|-|psql:db]"; + echo "in: - = STDIN or filename"; + echo "out: - = STDIN or filename or psql:database_name" + echo " psql:database_name will load the dump into the database" + echo " if out is omitted in is used for out (same file)" + echo "--str: different replacement string. Eg for Ubuntu use: '/usr/lib/postgresql/8.3/lib/liblwgeom'"; + echo "WARNING: A postgis dump is not meant to be distributed - it still may be useful :)" +} + +if [ -z "$1" -o "$1" = --help -o "$1" = -h ]; then + do_help; exit 1 +fi + +tostr='$libdir/'"$libName" +if [ "$1" == "--str" ]; then + to="$2"; shift 2 +fi + +i=$1 +o="${2:-$1}" + +cmd_in(){ + case "$i" in + -) cat;; + *) cat "$i";; + esac +} + +cmd_out(){ + case "$o" in + -) cat;; # stdout + psql:*) psql "${o:5}";; # pipe into psql + *) + t=`mktemp`; cat > "$t"; mv "$t" "$o" + ;; + esac +} + +cmd_replace(){ + contents=`cat` + # get wrong library path: + fromstr=$(echo "$contents" | head -n 50 | sed -n "s/.*AS '\([^']*\)'.*/\1/p" | head -n 1) + echo "$contents" | sed "s@AS '$fromstr@AS '$tostr@g" +} + +cmd_in | cmd_replace | cmd_out diff --git a/pkgs/lib/misc.nix b/pkgs/lib/misc.nix index 0a8c61d6c85c..32b30ee2fbff 100644 --- a/pkgs/lib/misc.nix +++ b/pkgs/lib/misc.nix @@ -294,7 +294,7 @@ rec { mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; } listToAttrs (map (n : nameValuePair n lib.concat) [ "buildNativeInputs" "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" ]) // listToAttrs (map (n : nameValuePair n lib.mergeAttrs) [ "passthru" "meta" "cfg" "flags" ]) - // listToAttrs (map (n : nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" ]) + // listToAttrs (map (n : nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ]) ; # returns atribute values as a list diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 76f3f0212282..0ac2592b0a82 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -5067,7 +5067,8 @@ let }; postgis = import ../development/libraries/postgis { - inherit stdenv fetchurl libxml2 postgresql geos proj perl; + inherit stdenv fetchurl libxml2 postgresql geos proj perl flex + composableDerivation; }; pth = import ../development/libraries/pth {