Cloning a row (even if the structure gets modified in the future)

A few years ago, I asked this question on StackExchange and got a brilliant answer (by Erwin Brandstetter). I just finally understood how it works. So here is my explanation (to myself mainly). Enjoy!

The goal was to INSERT a row in a table, cloning an existing one while replacing some value (like the primary key) in the new row. I didn’t want to list each and every column so that even if I add new fields to the table, the cloning mechanism would still work.

Here is the response I got:

INSERT INTO contrats
SELECT (sub.subalias).*
FROM (
    SELECT t #= hstore('idcontrat', nextval(pg_get_serial_sequence('contrats','idcontrat'))::TEXT)
             #= hstore('date_saisie', CURRENT_TIMESTAMP::TEXT)
             #= hstore('numero', numero || '-DUP')
             #= hstore('notes', NULL)
       AS subalias
       FROM contrats t
       WHERE idcontrat = :oldidcontrat
) sub
RETURNING idcontrat

First thing to know: when you create a table, PostgreSQL automatically creates a composite type with the same name and all fields in that table (see [here]). As you will discover in this documentation, you reference composite types with (parens).

So how does the query work? There’s an outer query:

INSERT INTO contrats 
SELECT (sub.subalias).* 
FROM (
    <inner_query>
) sub
RETURNING idcontrat.

This outer query is pretty obvious except the (sub.subalias) part.

The inner query is also simpler than it seems. If we didn’t want to change any field value, it would be:

SELECT t AS subalias
FROM contrats t
WHERE idcontrat = :oldidcontrat

Notice that we didn’t write SELECT t.* but just SELECT t. Here, t is the composite type that represents the whole contrats record/row.

Then we use the hstore PostgreSQL extension to do the transformations that we want. This is the syntax we use:

t #= hstore('fieldname',value)

This syntax only works on composite types and replaces the value of the fieldname field with the provided value. That value must be of type TEXT. As you can see, you can apply several transformations at once.

What was bugging me for so long was that in the initial answer I got, the second line was written:

SELECT (subalias).*

And I didn’t understand why that subalias was visible outside the inner query (I thought it was out of the scope).

subalias is just one field (of type contrats) and since it is of a composite type, you have to use the parens around the whole left part of the SELECT. You can’t write sub.(subalias).* but instead (sub.subalias).*

I must confess I asked the Perplexity AI to help me understand this.

Installing and configuring Zdkimfilter for courier-mta on Debian Buster (+ djbdns)

Download package

wget https://www.tana.it/sw/zdkimfilter/zdkimfilter-3.8.tar.gz

Install necessary packages

sudo apt install pkg-config libbsd-dev libssl-dev zlib1g-dev libunistring-dev libidn2-dev libopendbx1-dev

Compile and install

tar xfz zdkimfilter-3.8.tar.gz
cd zdkimfilter-3.8
./configure
make
sudo make install

Configure

Get superpowers :

sudo -i

Generate keys

cd /etc/courier/filters
mkdir keys
chown courier:courier keys
cd keys
/usr/local/bin/zdkimgenkey -s mydomain -d thisdomain.org

Here, the selector mydomain is just a name that I chose different from the real domain thisdomain.org for the purpose of this tutorial. You would normally use something like thisdomain.

chown courier:courier *

Setup the DNS

You have to put the public key that you just generated (the mydomain.txt file) into your DNS. It is provided in a bind-compatible format. Since I use djbdns, I have to transform the entry. I use the site https://andersbrownworth.com/projects/sysadmin/djbdnsRecordBuilder/#domainKeys to do the dirty work :

Just enter what follows p= in the TXT.

Configure

cd ..
mv zdkimfilter.conf.dist zdkimfilter.conf

Add a default domain at the end of the config file. I use thisdomain.org but you can use any domain. It is used when zdkimfilter cannot guess the real domain, that is, when the sender is something like paul (without @somedomain.tld).

It is recommended to also add the following lines :

no_signlen = Y
header_canon_relaxed = Y
body_canon_relaxed = Y
cd keys
ln -s mydomain.private thisdomain.org
filterctl start zdkimfilter

Lancer un script au démarrage

Pour lancer un script au démarrage du système « proprement » (en utilisant systemd) :

1. créer un script et le placer dans /usr/local/bin.

2. créer un fichier de configuration dans /etc/systemd/system/xxx.service

3. Y placer le contenu suivant :

[Unit]
Description=Bypass Dell fan control
Before=i8kmon.service

[Service]
ExecStart=/usr/local/bin/dell-bios-fan-control enable=1
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

4. Lancer systemctl daemon-reload

5. Activer le service avec systemctl enable xxx.service

La doc : https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Before=

Bullshit sites

Il y a parfois des sites qui valent le détour tant le n’importe quoi est poussé à son paroxysme. Florilège.

Okinaha – Le charlatanisme 2.0 – Ne vous contentez pas de cette page d’introduction, le site regorge d’attrape-nigauds pour personnes électrosensibles.
https://okinaha.com/collections/hygiene-electromagnetique/products/genatome-gtc-369-bouclier-electromagnetique-1

Répondeur courier-mta avec maildrop et mailbot

Il faut d’abord indiquer à courier d’utiliser un autre MDA (Mail Distribution Agent) :

/home/vmail/account/.courier :
|/usr/bin/maildrop .mailfilter

Puis indiquer les règles dans /home/vmail/account/.mailfilter :

cc "!joe@gosane.fr"
cc "| mailbot -A \"From: Account <account@gosane.fr>\" \
-N -c utf8 -T reply \
-s \"I'm on vacation\" \
-t 'vacation.txt' \
/usr/sbin/sendmail -f ''"
to "./Maildir"

Il faudra un fichier vacation.txt dans /home/vmail/account.

Raw SQL in Ruby/Rails

Everyone seems to discourage the use of raw SQL in Ruby applications and while ActiveRecord seems a good solution for general purpose CRUD operations, we have a strong expertise in SQL and we want to use it as much as possible. Here are the bits we have collected so far on the subject. We are new to Ruby/Rails so these might be obvious for some of you. We primarily write this for ourselves.

We are perfectly aware of the « limitations ». We love PostgreSQL and have no intention of being RDBMS-agnostic. At all.

find_by_sql the way we want it

We want named parameters because, despite the overhead, it’s the cleanest way to pass parameters (we don’t have to preserve a strict order which can lead to problems when enhancing the query, counting the « ? », etc). Also, when we use the same parameter several times in the same query, we don’t have to repeat it.

class ClientsController < ApplicationController

	def index
		@clients = Client.find_by_sql(
			<<-SQL
			SELECT idclient,name,email,contacts
			FROM clients 
			ORDER BY nom
			SQL
			)
	end

	def show
		@client = Client.find_by_sql(["	
			SELECT idclient,name,email,contacts 
			FROM clients 
			WHERE idclient = :idclient", 
			{ :idclient => params[:id] } 
		])[0]
	end

For the show method, we have to grab the first element in the array (thus the [0]at the end.

TdxSpreadSheet creation and filling via code

Basic usage and formatting

procedure TForm1.b1Click(Sender: TObject);
Var xls:TdxSpreadSheet;
    sh: TdxSpreadSheetTableView;
begin
  xls:=TdxSpreadSheet.Create(Self);
  Try
    xls.BeginUpdate;
    xls.ClearAll;
    sh:=TdxSpreadSheetTableView(xls.AddSheet('Bénéficiaires'));

    // row,col
    if Cells[1,1]=Nil then
      CreateCell(1,1);
    Cells[Row,Col].AsString:='test';
    sh.cells[1,1].Style.Borders[bLeft].Style:=sscbsDouble;
    sh.cells[1,1].Style.Borders[bRight].Color:=clred;
    sh.Cells[1,1].Style.Brush.BackgroundColor:=clcxLightGray;
    sh.Cells[1,1].Style.AlignHorz:=ssahCenter;
    sh.Cells[1,1].Style.DataFormat.FormatCode:='dd/mm/yyyy';
    sh.Cells[1,1].Style.DataFormat.FormatCode:='# ##0.00';
    sh.Cells[1,1].Style.Font.Style:=[fsBold];

    // Formula
    CreateCell(2,1); // B3
    sh.Cells[2,1].SetText('=SUM(B2:B2)',true);

    xls.EndUpdate;
    xls.SaveToFile('C:\Users\gosane\Desktop\text.xlsx');
  Finally
    xls.Free;
  End;
end;

Helpers

function xlscolname(i:integer):string;
var a,b:integer;
begin
  if i<0 then
    result:='?'
  else if i<26 then
    result:=chr(65+i)
  else begin
    a:=i div 26;
    b:=i mod 26;
    result:=chr(64+a)+chr(65+b);
  end;
end;

Working with TPgDAC (DevArt components for Delphi)

TPgLoader

interface uses DALoader,PgLoader;

Type TMyForm = Class(TForm)
       // ...
       private
         procedure PgLoader1PutData(Sender: TDALoader);
     End;

{...}

procedure TFxxx.PgLoader1PutData(Sender: TDALoader);
var i:Integer;
begin
  for i:=1 to 10 do
    Sender.PutColumnData('fieldname',i,Value);
end;


procedure TFxxx.Import;
Var pgl:TPgLoader;
begin
  pgl:=TPgLoader.Create(Application);
  Try
    pgl.Connection:=DM.PgConnection1;
    pgl.TableName:='MyTableName';
    pgl.Options.BufferSize:=65536;
    // pgl.OnProgress:=LoaderProgress;
    pgl.OnPutData:=PgLoader1PutData;
    pgl.CreateColumns;
    // Remove primary key from PgLoader
    for I := 0 to pgl.Columns.Count-1 do
      if pgl.Columns[i].Name='idprimarykey' then begin
        pgl.Columns.Delete(i);
        break;
      end;
    pgl.Load;
  Finally
    pgl.Free;
  End;
end;

KDE5 – Hints and tips

Autostarting applications

Plasma can autostart applications and run scripts on startup and shutdown. To autostart an application, navigate to System Settings > Startup and Shutdown > Autostart and add the program or shell script of your choice. For applications, a .desktop file will be created, for shell scripts, a symlink will be created.

Note:

Programs can be autostarted on login only, whilst shell scripts can also be run on shutdown or even before Plasma itself starts.
Shell scripts will only be run if they are marked executable.

Place Desktop entries (i.e. .desktop files) here:

~/.config/autostart : for starting applications at login.

Place or symlink shell scripts in one of the following directories:

~/.config/plasma-workspace/env : for executing scripts at login before launching Plasma.

~/.config/autostart-scripts : for executing scripts at login.

~/.config/plasma-workspace/shutdown : for executing scripts on shutdown.

Source : https://wiki.archlinux.org/index.php/KDE#Autostarting_applications