summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Spek <p.spek@tyil.nl>2021-04-01 07:55:09 +0200
committerPatrick Spek <p.spek@tyil.nl>2021-04-01 07:55:09 +0200
commit224b7c7a557b6060535fe127de7be29d5142d568 (patch)
treead1e112f6d3d054c519af7d25a831204523df739
parent67a16b1cde665f986fc99626035e23efcee32920 (diff)
downloadblog-224b7c7a557b6060535fe127de7be29d5142d568.tar.gz
blog-224b7c7a557b6060535fe127de7be29d5142d568.tar.bz2
Two posts, lost forever on my old desktop
rip sessifet.tyil.net
-rw-r--r--src/_posts/2020-12-14-raku-modules-in-gentoo-portage.md114
-rw-r--r--src/_posts/2020-12-15-merging-json-in-postgresql.md50
2 files changed, 164 insertions, 0 deletions
diff --git a/src/_posts/2020-12-14-raku-modules-in-gentoo-portage.md b/src/_posts/2020-12-14-raku-modules-in-gentoo-portage.md
new file mode 100644
index 0000000..2d268d1
--- /dev/null
+++ b/src/_posts/2020-12-14-raku-modules-in-gentoo-portage.md
@@ -0,0 +1,114 @@
+---
+layout: post
+tags: Raku Gentoo
+social:
+ email: mailto:~tyil/public-inbox@lists.sr.ht&subject=Raku modules in Gentoo's Portage
+description: >
+ Updates are important. This article aims to help you to learn from my
+ mistakes, so your updates will go smooth.
+---
+
+The last couple of days I've been taking another look at getting modules for
+the Raku programming language into Gentoo's Portage tree. Making new packages
+available in Gentoo is incredibly easy with their overlay system.
+
+The more complex part was Raku's side of things. While most languages just have
+a certain directory to drop files in, Raku *should* use a
+`CompUnit::Repository` object, which exposes the `.install` method. This is
+obviously slower than just copying the files around, but there are merits to
+this method. For one, it allows installation of the same module with different
+versions, or from different authors. It also handles all the Unicode complexity
+for you.
+
+{% admonition_md note %}
+There *is* a
+[CompUnit::Repository::FileSystem](https://docs.raku.org/type/CompUnit::Repository::FileSystem)
+which would allow me to just copy over files to the right directory, however, I
+quite like the ability to have multiple versions of the same module installed.
+This is actually something Portage is designed with, too!
+{% endadmonition_md %}
+
+After an email to the Raku users mailing list, I got some pointers over IRC. I
+let these sink in for a couple days, considering how to approach the problem
+properly. Then, one night, a solution came to mind, and I set out to test it.
+
+*It actually worked*. And a similar method should be usable for other
+distributions too, such as Debian, OpenSUSE or Archlinux, to create packages
+out of Raku modules. This should greatly improve the ability to ship Raku
+programs to end-users, without requiring them to learn how Raku's ecosystem is
+modeled, or which module manager it uses.
+
+The most important part of this approach is the
+[`module-installer.raku`](https://git.sr.ht/~tyil/raku-overlay/tree/7494c81524ec1845c77dabfbb3303a34eb4b89f4/item/dev-lang/raku/files/module-installer.raku)
+program, which is part of `dev-lang/raku::raku-overlay`. It accepts a path to
+the module to install. It does not depend on any one module manager, so it can
+be used to bootstrap a user-friendly module manager (such as
+[`zef`](https://github.com/ugexe/zef/)) for the user.
+
+{% highlight raku %}
+#| Install a Raku module.
+sub MAIN (
+ #| The path to the Raku module sources.
+ IO() $path,
+
+ #| The repository to install it in. Options are "site" (ment for
+ #| user-installed modules), "vendor" (ment for distributions that want
+ #| to include more modules) and "core" (ment for modules distributed
+ #| along with Raku itself).
+ Str:D :$repo = 'site',
+
+ #| Force installation of the module.
+ Bool:D :$force = True,
+) {
+ CATCH {
+ default { $_.say; exit 1; }
+ }
+
+ die "This script should be used by Portage only!" unless %*ENV<D>;
+
+ my $prefix = %*ENV<D>.IO.add('usr/share/perl6').add($repo);
+ my $repository = CompUnit::Repository::Installation.new(:$prefix);
+ my $meta-file = $path.add('META6.json');
+ my $dist = Distribution::Path.new($path, :$meta-file);
+
+ $repository.install($dist, :$force);
+}
+{% endhighlight %}
+
+It's a fairly straightforward program. It checks for `$D` to be set in the
+environment, which is a variable Portage sets as the destination directory to
+install new files in. This directory gets merged into the root filesystem to
+finalize installation of any package.
+
+If `$D` is set, I append the path used by Raku in Gentoo to it, followed by a
+repo name. Next I create a `CompUnit::Repository` using this path. This is a
+trick to get the files to appear in the right directory for Portage, to
+eventually merge them in the system-wide `site` module repo used by Raku.
+Additionally, I can use the `CompUnit::Repository`'s `install` method to handle
+all the Raku specific parts that I don't want to handle myself.
+
+This leaves one last issue. By creating this new repo, I also get a couple
+files that already exist in the system wide `site` repo. Portage will complain
+about possible file collisions and refuse to install the package if these
+remain. However, this can be solved rather easily by calling `rm` on these files.
+
+{% highlight sh %}
+rm -- "${D}/usr/share/perl6/site/version"
+rm -- "${D}/usr/share/perl6/site/repo.lock"
+rm -- "${D}/usr/share/perl6/site/precomp/.lock"
+{% endhighlight %}
+
+And with this, my test module, `IO::Path::XDG`, installs cleanly through the
+power of Portage, and is usable by all users using the system-wide Raku
+installation.
+
+To make this work for other distributions, the `module-installer.raku` program
+should be modified slightly. Most notably, the `$prefix` must be altered to
+point towards the right directory, so the files will be installed into whatever
+directory will end up being packaged. Other than that, the standard means of
+packaging can be followed.
+
+For the Gentoo users, this overlay is available at
+[SourceHut](https://git.sr.ht/~tyil/raku-overlay). It currently holds only
+`IO::Path::XDG` (`dev-raku/io-path-xdg`), but you are invited to try it out and
+report any issues you may encounter.
diff --git a/src/_posts/2020-12-15-merging-json-in-postgresql.md b/src/_posts/2020-12-15-merging-json-in-postgresql.md
new file mode 100644
index 0000000..0d7e087
--- /dev/null
+++ b/src/_posts/2020-12-15-merging-json-in-postgresql.md
@@ -0,0 +1,50 @@
+---
+layout: post
+tags: PostgreSQL Programming JSON
+social:
+ email: mailto:~tyil/public-inbox@lists.sr.ht&subject=Merging JSON objects in PostgreSQL
+description: >
+ Left unsatisfied trying to find a nice way to merge two JSON objects in
+ PostgreSQL, I whipped up my own. This small post shows off my glorious
+ concoction for future generations."
+---
+
+At my `$day-job` we have a lot of `jsonb` in our database. From time to time, I
+have to manually run a query to fix something in there. This week was one of
+those times.
+
+While you can pretty much do everything you need with regards to JSON editing
+with `jsonb_se`t, I thought it might be nice if I were able to *merge* a given
+JSON object into an existing object. This might be cleaner in some situations,
+but mostly it is fun to figure it out. And who doesn’t like spending time with
+`plpgsql`?
+
+The way I wanted to have it work is like this:
+
+{% highlight sql %}
+UPDATE user SET properties = jsonb_merge(properties, '{"notifications": {"new_case": false, "new_document": true}}');
+{% endhighlight %}
+
+And this is the eventual function I produced to do it:
+
+{% highlight sql %}
+CREATE OR REPLACE FUNCTION jsonb_merge(original jsonb, delta jsonb) RETURNS jsonb AS $$
+ DECLARE result jsonb;
+ BEGIN
+ SELECT
+ json_object_agg(
+ COALESCE(original_key, delta_key),
+ CASE
+ WHEN original_value IS NULL THEN delta_value
+ WHEN delta_value IS NULL THEN original_value
+ WHEN (jsonb_typeof(original_value) <> 'object' OR jsonb_typeof(delta_value) <> 'object') THEN delta_value
+ ELSE jsonb_merge(original_value, delta_value)
+ END
+ )
+ INTO result
+ FROM jsonb_each(original) e1(original_key, original_value)
+ FULL JOIN jsonb_each(delta) e2(delta_key, delta_value) ON original_key = delta_key;
+ RETURN result;
+END
+$$ LANGUAGE plpgsql;
+{% endhighlight %}