Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

私は如何にして心配するのを止めて年賀状の宛名を手書きするようになったか

ポエムです。

背景

年賀状の宛名なんて、筆まめやら何やらで印刷すればいいとも思うんですよ。特に、私はコンピュータ・ソフトウェア・エンジニアなので、自動化はまさに自分の存在意義に関わる訳です。
でも、そういう訳にもいかない事情があるわけです。主に人間系で。

年賀状の宛先には、コンピュータ・エンジニアリングを解さない人もいます。もっと言うと、コンピュータを解さない人がいます。そういう人にとって、コンピュータは「字引き」です。「辞書」じゃないですよ?「字引き」です。アイコンという概念は理解できないので、コンピュータが動作している様子を見ても、ひらがなが漢字に変わることだけを認識して「これは字引きだ」と理解する訳です。話がそれました。

若い人でコンピュータを解さない人もいますが、そういう人は単にコンピュータに無関心なだけなので、宛名が印刷だろうが手書きだろうが問題ないと思います。もっと言うと、若いがために、そこから文句が出ても、封建社会の中で自分が受けるダメージはさほど大きくない。

リスク

問題は、一族の中で発言力を持つ人が、印刷された宛名に対して何かを気にかけたケースで、かつ自分がそこからダメージを受けるケースです。なので、たとえ自分は宛名が印刷された年賀状を受け取っているとしても、何の助けにもなりません。宛名を印刷する人は、文句を言う側の人かもしれません。それに、自分宛の年賀状の宛先面を、自分が年賀状を書く相手に見せたりしないですよね?

リスクとしては、たとえば「年賀状をすべて配偶者に作らせているのではないか」という疑惑が発生するケースが考えられます。これは配偶者が専業主婦/専業主夫だと発生しやすそうにも思われますが、かといって共働きだからといって発生しない訳ではないので(なぜかという話は土地・時代の背景によるので省略)、回避しておくに越したことはありません。

回避策

そして、このリスクを回避(低減ではなく回避です)するために、宛名を手書きするわけです。リスクの低減策として以下のような対策も考えられますが、リスク対策コストの面から採用はやめました。

  • 宛名(表面)は印刷して、裏面は手作り
    • 本当はこれがやりたかったんだけど、幼子のいる家では無理ですねコレ……
  • 宛名も(表面)も裏面も印刷して、裏面にコメントを書く
    • 自分のまわりではこれが多いですね。ただ、コメント考えるの大変じゃないですか?宛名書く方がラクじゃないですか?
  • 宛名(表面)を印刷する人と、手書きする人とを分ける
    • 管理が大変だし、高々数十枚なら手順を揃えた方が運用系がラクです。管理を間違えてリスク回避に失敗してもつまらないし。

There are no properties for ordinary characters in PropList.txt

Problem

When run the script in next URL with PropList.txt on unicode.org, result file did not contain character properties for ordinary characters like 'x', 'y', or 'z'. http://satob.hatenablog.com/entry/2017/11/21/002957

Reason

PropList.txt does not cover all the characters in the Unicode Standard. The properties for all the characters are in Scripts.txt.

Note there are no mention for Scripts.txt on UNICODE CHARACTER DATABASE page.

Solution

Use Scripts.txt rather than PropList.txt.

Get CodePoint-Property Pair from Scripts.txt on Unicode.org

Context

You want to make a list of pair of unicode codepoint and its character property, like below:

00009,Cc
00020,Zs
00021,Po
00024,Sc
...

Solution with PowerShell

You can make the list from ftp://ftp.unicode.org/Public/UNIDATA/PropList.txt ftp://ftp.unicode.org/Public/UNIDATA/Scripts.txt with PowerShell:

Get-Content ./Scripts.txt | `
  Where-Object { ($_ -notlike "#*") -and ($_ -notlike "") } | `
  ForEach-Object {
    $_ -match '(?<CodePoint>[0-9A-F]+(\.\.[0-9A-F]+)?)\s+;\s+(\w+) # (?<PatternName>\w+)' > $null;
    $CodePoint = $Matches.CodePoint;
    $PatternName = $Matches.PatternName;
    if ($CodePoint -like '*..*') {
      $StartCodePoint = [Convert]::ToInt32(($CodePoint -split "\.\.")[0], 16);
      $EndCodePoint = [Convert]::ToInt32(($CodePoint -split "\.\.")[1], 16);
      $StartCodePoint..$EndCodePoint | ForEach-Object {
        $_.ToString('X5') + ',' + $PatternName
      }
    } else {
      [Convert]::ToInt32($CodePoint, 16).ToString('X5') + ',' + $PatternName
    }
  } | `
  Sort-Object | Get-Unique | Out-File DetailedPropList.txt -Encoding utf8

Ordinaly SELECT clause returns ORA-00904 error on Oracle in SQL Fiddle

Context

The "Text to DDL" feature on SQL Fiddle generates DDL like below for Oracle 11g R2.

CREATE TABLE Table1
    ("value1" int)
;

INSERT ALL 
    INTO Table1 ("value1")
         VALUES (1)
SELECT * FROM dual
;

Problem

This ordinal SELECT clasuse returns ORA-00904: "VALUE1": invalid identifier eror on this table.

select value1 from table1;

Reason

This is caused by design of Oracle, and "Text to DDL" feature on SQL Fiddle.

"Text to DDL" feature on SQL Fiddle always quote column name. In Oracle, quoted column names are treated as case sensitive name, and on the other hand, unquoted column names are treated as capitalized names.

It means CREATE TABLE Table1 ("value1" int); creates a table with a column named value1 (case sensitive), and select value1 from table1; searchs for a column named VALUE1.

Solution

Remove quotes from DDL like:

CREATE TABLE Table1 (value1 int);
INSERT INTO Table1 (value1) VALUES (1);
select value1 from table1;

Or, add quotes to DML like:

CREATE TABLE Table1 ("value1" int);
INSERT INTO Table1 ("value1") VALUES (1);
select "value1" from table1;

Return value of comparison operator in SELECT clause

Background

Some RDBMS can contain the result of comparison operator in SELECT clause. However, the returned values are different between RDBMS.

Result

MySQL

I used MySQL 5.6 on SQL Fiddle.

DDL (MySQL)

CREATE TABLE Table1 (`value1` int, `value2` int, `value3` int);

INSERT INTO Table1 (`value1`, `value2`, `value3`)
VALUES             (1, 2, 3),
                   (2, 4, 6),
                   (3, 6, 9);

DML (MySQL)

select value1, value2, value3, value1=1, value2=4, value3=9 from table1;

Result (MySQL)

| value1 | value2 | value3 | value1=1 | value2=4 | value3=9 |
|--------|--------|--------|----------|----------|----------|
|      1 |      2 |      3 |        1 |        0 |        0 |
|      2 |      4 |      6 |        0 |        1 |        0 |
|      3 |      6 |      9 |        0 |        0 |        1 |

PostgreSQL

I used PostgreSQL 9.6 on SQL Fiddle.

DDL (PostgreSQL)

CREATE TABLE Table1 ("value1" int, "value2" int, "value3" int);

INSERT INTO Table1 ("value1", "value2", "value3")
VALUES             (1, 2, 3),
                   (2, 4, 6),
                   (3, 6, 9);

DML (PostgreSQL)

select value1, value2, value3, value1=1, value2=4, value3=9 from table1;

Result (PostgreSQL)

| value1 | value2 | value3 | ?column? | ?column? | ?column? |
|--------|--------|--------|----------|----------|----------|
|      1 |      2 |      3 |     true |    false |    false |
|      2 |      4 |      6 |    false |     true |    false |
|      3 |      6 |      9 |    false |    false |     true |

SQL Server 2014

I used SQL SQL Server 2014 on SQL Fiddle.

DDL (SQL Server)

CREATE TABLE Table1
    ("value1" int, "value2" int, "value3" int)
;
    
INSERT INTO Table1 ("value1", "value2", "value3") VALUES (1, 2, 3);
INSERT INTO Table1 ("value1", "value2", "value3") VALUES (2, 4, 6);
INSERT INTO Table1 ("value1", "value2", "value3") VALUES (3, 6, 9);

DML (SQL Server)

Note that value2=4 returns always 4. It doesn't cause any error, but it must be unexpected result. You have to use case when instead of = operator.

select
  value1, value2, value3, 
  case when value1 = 1 then 1 else 0 end,
  case when value2 = 4 then 1 else 0 end,
  case when value3 = 9 then 1 else 0 end
from table1;

Result (SQL Server)

| value1 | value2 | value3 |   |   |   |
|--------|--------|--------|---|---|---|
|      1 |      2 |      3 | 1 | 0 | 0 |
|      2 |      4 |      6 | 0 | 1 | 0 |
|      3 |      6 |      9 | 0 | 0 | 1 |

Oracle

I used Oracle 11g R2 on SQL Fiddle.

DDL (Oracle)

CREATE TABLE Table1
    (value1 int, value2 int, value3 int)
;
    
INSERT INTO Table1 (value1, value2, value3) VALUES (1, 2, 3);
INSERT INTO Table1 (value1, value2, value3) VALUES (2, 4, 6);
INSERT INTO Table1 (value1, value2, value3) VALUES (3, 6, 9);

DML (Oracle)

Note that value2=4 in SELECT clause causes "ORA-00923: FROM keyword not found where expected" error. You have to use case when instead of = operator.

select
  value1, value2, value3,
  case when value1 = 1 then 1 else 0 end,
  case when value2 = 4 then 1 else 0 end,
  case when value3 = 9 then 1 else 0 end
from table1;

Result (Oracle)

| VALUE1 | VALUE2 | VALUE3 | CASEWHENVALUE1=1THEN1ELSE0END | CASEWHENVALUE2=4THEN1ELSE0END | CASEWHENVALUE3=9THEN1ELSE0END |
|--------|--------|--------|-------------------------------|-------------------------------|-------------------------------|
|      1 |      2 |      3 |                             1 |                             0 |                             0 |
|      2 |      4 |      6 |                             0 |                             1 |                             0 |
|      3 |      6 |      9 |                             0 |                             0 |                             1 |