memo-pad’s blog

自分のためのメモをまとめています。ここに書いてある内容については責任は負いません。全て自己責任でお願いします。

LinuxMint(Mate)で範囲指定スクリーンショットのショートカット作成

状況

  • LinuxMint 18.1のMate版
$  cat /etc/lsb-release 
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=18.1
DISTRIB_CODENAME=serena
DISTRIB_DESCRIPTION="Linux Mint 18.1 Serena"
  • 「LinuxMint スクリーンショット 範囲選択 ショートカット」とかでググるとこんな感じの内容があるが出来ない

    Shift+PrintScreen
    端末から実行する場合のコマンド
    $ gnome-screenshot --area

ちょっと調べてみる

  • そもそもShift+PrintScreenのショートカットが登録されてない
  • LinuxMint 18.1(Mate)にはgnome-screenshotは入ってない
    • 代わりにmate-screenshotが入っている

対応方法

名前:スクリーンショット(範囲選択)
コマンド:sh -c 'sleep 0.3; mate-screenshot -a'

ショートカット作成

操作を追加

  • Menu -> 設定 -> キーボードショートカットを選択 f:id:memo-pad:20181008175746p:plain

  • キーボードショートカット画面でAddボタンをクリック f:id:memo-pad:20181008175806p:plain

  • 名前に「スクリーンショット(範囲選択)」、コマンドに「sh -c 'sleep 0.3; mate-screenshot -a'」と入力し、Applyをクリック *1 f:id:memo-pad:20181008175813p:plain

ショートカットキーの割当

  • 右のショートカット部分をクリックし、ショートカットキーを入力 f:id:memo-pad:20181008175820p:plain

  • 想定通りのキー(今回はShift+Print)が登録されてることを確認し、作成完了 f:id:memo-pad:20181008175828p:plain

*1:コマンド部分のsleep時間が短すぎると、すぐにショートカットキー入力後にキーを離さないといけなくなるので、ここは好みの時間に設定してください

SpringBootでPartial Response

状況

  • API作るときに、fields=xxx,yyy,zzzというように欲しいフィールドだけ指定できるようにしたい

実現方法

  • 返り値をMappingJacksonValueに変更し、Filterを設定することで実現
  • コードはこちら github.com

具体的な実装

データクラス

  • Filter対象のクラスに@JsonFilter()で名前をつける
@Data
@AllArgsConstructor
@JsonFilter("User")
public class User {
    private String id;
    private String name;
    private UserInfo userInfo;
}
@Data
@AllArgsConstructor
public class UserInfo {
    private String tel;
    private String address;
}

コントローラ

  • 返り値はUserではなく、MappingJacksonValueで返す
    • SimpleFilterProviderのaddFilterでFilterを作成
    • 第一引数には@JsonFilterで指定した名前を、第二引数にはフィルタープロパティを設定
    • 今回はfilterOutAllExcept(指定した物以外をすべてフィルタ)を利用
@RestController
public class ResponseFilterController {

    private final Map<String, User> users = new HashMap<String, User>() {
        {
            put("1", new User("1", "user1", new UserInfo("xxx-xxxx-1111", "XXXXXXXXXXXXX1")));
            put("2", new User("2", "user2", new UserInfo("xxx-xxxx-2222", "XXXXXXXXXXXXX2")));
            put("3", new User("3", "user3", new UserInfo("xxx-xxxx-3333", "XXXXXXXXXXXXX3")));

        }
    };

    @GetMapping("/user/{user_id}")
    MappingJacksonValue getSingleUser(
            @PathVariable("user_id") String userId,
            @RequestParam(value = "fields", defaultValue = "name", required = false) String fieldParam
    ) {
        User user = users.get(userId);

        return createMappingJacksonValue(fieldParam, user);
    }

    private MappingJacksonValue createMappingJacksonValue(String fieldParam, Object value) {
        String[] fields = fieldParam.split(",", 0);

        MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(value);
        FilterProvider filters = new SimpleFilterProvider()
                // 第一引数には@JsonFilterで指定した名前、第二引数にはフィルタープロパティ
                // filterOutAllExcept(指定した物以外をすべてフィルタ)
                .addFilter("User", SimpleBeanPropertyFilter.filterOutAllExcept(fields));
        mappingJacksonValue.setFilters(filters);
        return mappingJacksonValue;
    }
}

application.propeties

  • レスポンスのfieldをSnakeCaseに(あってもなくても可)
spring.jackson.property-naming-strategy=SNAKE_CASE

実行結果

  • fields=id,nameと指定 f:id:memo-pad:20181008164612p:plain

  • fields=id,name,user_infoと指定
    こんな感じでuser_info配下を一括で表示制御もできる f:id:memo-pad:20181008164633p:plain

Filter対象のクラスを含むクラスの場合

こんな感じに件数と複数のUserを持つクラスの場合も、User側にフィルタ設定があるので特にフィルタを追加することなく実現可能

データクラス

@Data
@AllArgsConstructor
public class UserResponse {
    private Integer totalResults;
    private Collection<User> results;
}

コントローラ

 @GetMapping("/user")
    MappingJacksonValue getUser(
            @RequestParam(value = "fields", defaultValue = "name", required = false) String fieldParam
    ) {
        UserResponse userResponse = new UserResponse(users.size(), users.values());

        return createMappingJacksonValue(fieldParam, userResponse);
    }

実行結果

  • fields=id,nameと指定
    こんな感じにJsonFilter指定したクラスを要素に持つ場合もちゃんとフィルタされる f:id:memo-pad:20181008164648p:plain

Spring Data JPAのN+1問題解決とMultipleBagFetchExceptionの回避方法

概要

以下のメモ

  • JPAで@OneToManyの要素を取得するときにN+1で取得してしまうので、その際の挙動と解決策
  • N+1問題解決のために@OneToManyを複数種類JOIN FETCHする際のMultipleBagFetchExceptionの回避方法

TL;DR

  • 1回のSQLで@OneToManyの要素を1種類取得したい場合は、JOIN FETCHで取得
  • 1回のSQLで@OneToManyの要素を複数種類取得したい場合は、MultipleBagFetchExceptionが発生してしまうため、List型ではなくSet型にしてJOIN FETCHで取得

今回の環境

  • テーブルの関係は図を参照
  • Parentが@OneToManyでChildOneとChildTwoを複数持つ f:id:memo-pad:20181006123539j:plain

  • コードはこちら

github.com

Data

INSERT INTO parent(id) VALUES (1)
INSERT INTO parent(id) VALUES (2)

INSERT INTO child_one(id,parent_id) VALUES (1,1)
INSERT INTO child_one(id,parent_id) VALUES (2,1)
INSERT INTO child_one(id,parent_id) VALUES (3,2)

INSERT INTO child_two(id,parent_id) VALUES (1,1)
INSERT INTO child_two(id,parent_id) VALUES (2,2)
INSERT INTO child_two(id,parent_id) VALUES (3,2)

Entity

  • Parent
@Table(name = "parent")
@Entity
@Data
public class Parent {
    @Id
    private Integer id;

    @OneToMany(mappedBy = "parent")
    private List<ChildOne> childOnes;

    @OneToMany(mappedBy = "parent")
    private List<ChildTwo> childTwos;
}
  • ChildOne
@Table(name = "child_one")
@Entity
@Data
@ToString(exclude = "parent")
public class ChildOne {
    @Id
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parentId", foreignKey = @ForeignKey(ConstraintMode.PROVIDER_DEFAULT))
    private Parent parent;
}
  • ChildTwo
@Table(name = "child_two")
@Entity
@Data
@ToString(exclude = "parent")
public class ChildTwo {

    @Id
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parentId", foreignKey = @ForeignKey(ConstraintMode.PROVIDER_DEFAULT))
    private Parent parent;
}

単純にfindAllでParent要素を全取得した場合

😥 Parentの全要素に対して、ChildOne, ChildTwo取得のSQLを毎回投げてしまう。

挙動

  • Parentを取得
Hibernate:
    select
        parent0_.id as id1_5_
    from
        parent parent0_
  • Parent(id=1)のChildOneとChildTwoを取得
Hibernate:
    select
        childones0_.parent_id as parent_i2_0_0_,
        childones0_.id as id1_0_0_,
        childones0_.id as id1_0_1_,
        childones0_.parent_id as parent_i2_0_1_
    from
        child_one childones0_
    where
        childones0_.parent_id=?
Hibernate:
    select
        childtwos0_.parent_id as parent_i2_1_0_,
        childtwos0_.id as id1_1_0_,
        childtwos0_.id as id1_1_1_,
        childtwos0_.parent_id as parent_i2_1_1_
    from
        child_two childtwos0_
    where
        childtwos0_.parent_id=?
Parent(id=1, childOnes=[ChildOne(id=1), ChildOne(id=2)], childTwos=[ChildTwo(id=1)])
  • Parent(id=2)のChildOneとChildTwoを取得
Hibernate:
    select
        childones0_.parent_id as parent_i2_0_0_,
        childones0_.id as id1_0_0_,
        childones0_.id as id1_0_1_,
        childones0_.parent_id as parent_i2_0_1_
    from
        child_one childones0_
    where
        childones0_.parent_id=?
Hibernate:
    select
        childtwos0_.parent_id as parent_i2_1_0_,
        childtwos0_.id as id1_1_0_,
        childtwos0_.id as id1_1_1_,
        childtwos0_.parent_id as parent_i2_1_1_
    from
        child_two childtwos0_
    where
        childtwos0_.parent_id=?
Parent(id=2, childOnes=[ChildOne(id=3)], childTwos=[ChildTwo(id=2), ChildTwo(id=3)])

ParentとChildOneをJoinして取得

😐 ParentとChildOneを先にJoinした結果を取得しておくので、ChildOne取得分は減らせる

  • Repository
public interface ParentRepository extends JpaRepository<Parent, Integer> {

    @Query("SELECT DISTINCT x FROM Parent x " +
            "LEFT JOIN FETCH x.childOnes")
    List<Parent> findParentWithSingleJoin();
}

挙動

  • ParentとChildOneをJoinした結果を取得
Hibernate:
    select
        distinct parent0_.id as id1_5_0_,
        childones1_.id as id1_0_1_,
        childones1_.parent_id as parent_i2_0_1_,
        childones1_.parent_id as parent_i2_0_0__,
        childones1_.id as id1_0_0__
    from
        parent parent0_
    left outer join
        child_one childones1_
            on parent0_.id=childones1_.parent_id
  • Parent(id=1)のChildTwoを取得
Hibernate:
    select
        childtwos0_.parent_id as parent_i2_1_0_,
        childtwos0_.id as id1_1_0_,
        childtwos0_.id as id1_1_1_,
        childtwos0_.parent_id as parent_i2_1_1_
    from
        child_two childtwos0_
    where
        childtwos0_.parent_id=?
Parent(id=1, childOnes=[ChildOne(id=1), ChildOne(id=2)], childTwos=[ChildTwo(id=1)])
  • Parent(id=2)のChildTwoを取得
Hibernate:
    select
        childtwos0_.parent_id as parent_i2_1_0_,
        childtwos0_.id as id1_1_0_,
        childtwos0_.id as id1_1_1_,
        childtwos0_.parent_id as parent_i2_1_1_
    from
        child_two childtwos0_
    where
        childtwos0_.parent_id=?
Parent(id=2, childOnes=[ChildOne(id=3)], childTwos=[ChildTwo(id=2), ChildTwo(id=3)])

ParentとChildOneとChildTwoをJoinして取得

😱 複数のListをJoinで取得しようとするとorg.hibernate.loader.MultipleBagFetchExceptionが発生してしまう

  • Repository
public interface ParentRepository extends JpaRepository<Parent, Integer> {
    // org.hibernate.loader.MultipleBagFetchExceptionが発生してしまう
    @Query("SELECT DISTINCT x FROM Parent x " +
            "LEFT JOIN FETCH x.childOnes " +
            "LEFT JOIN FETCH x.childTwos")
    List<Parent> findParentWithDoubleJoin();
}
  • org.hibernate.loader.MultipleBagFetchException
Caused by: java.lang.IllegalArgumentException: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.example.jpa_n_plus_one.entity.Parent.childOnes, com.example.jpa_n_plus_one.entity.Parent.childTwos]

ParentとChildOneとChildTwoをJoinして取得 (MultipleBagFetchException回避版)

😊 1回のSQLで全要素を取得可能

  • Parentの@OneToMany部分をList型にするとMultipleBagFetchExceptionが発生してしまうため、Set型に変更したもので行う

  • Repository

public interface NeoParentRepository extends JpaRepository<NeoParent, Integer> {

    @Query("SELECT DISTINCT x FROM NeoParent x " +
            "LEFT JOIN FETCH x.neoChildOnes " +
            "LEFT JOIN FETCH x.neoChildTwos")
    List<NeoParent> findParentWithDoubleJoin();
}

Data (MultipleBagFetchException回避版)

INSERT INTO neo_parent(id) VALUES (1)
INSERT INTO neo_parent(id) VALUES (2)

INSERT INTO neo_child_one(id,neo_parent_id) VALUES (1,1)
INSERT INTO neo_child_one(id,neo_parent_id) VALUES (2,1)
INSERT INTO neo_child_one(id,neo_parent_id) VALUES (3,2)

INSERT INTO neo_child_two(id,neo_parent_id) VALUES (1,1)
INSERT INTO neo_child_two(id,neo_parent_id) VALUES (2,2)
INSERT INTO neo_child_two(id,neo_parent_id) VALUES (3,2)

Entity (MultipleBagFetchException回避版)

  • NeoParent
@Table(name = "neo_parent")
@Entity
@Data
@EqualsAndHashCode(exclude = {"neoChildOnes", "neoChildTwos"})
public class NeoParent {
    @Id
    private Integer id;

    @OneToMany(mappedBy = "neoParent")
    private Set<NeoChildOne> neoChildOnes;

    @OneToMany(mappedBy = "neoParent")
    private Set<NeoChildTwo> neoChildTwos;
}
  • NeoChildOne
@Table(name = "neo_child_one")
@Entity
@Data
@ToString(exclude = "neoParent")
public class NeoChildOne {
    @Id
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "neoParentId", foreignKey = @ForeignKey(ConstraintMode.PROVIDER_DEFAULT))
    private NeoParent neoParent;
}
  • NeoChildTwo
@Table(name = "neo_child_two")
@Entity
@Data
@ToString(exclude = "neoParent")
public class NeoChildTwo {

    @Id
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "neoParentId", foreignKey = @ForeignKey(ConstraintMode.PROVIDER_DEFAULT))
    private NeoParent neoParent;
}

挙動

  • NeoParentとNeoChildOneとNeoChildTwo をJoinした結果を取得
Hibernate:
    select
        distinct neoparent0_.id as id1_4_0_,
        neochildon1_.id as id1_2_1_,
        neochildtw2_.id as id1_3_2_,
        neochildon1_.neo_parent_id as neo_pare2_2_1_,
        neochildon1_.neo_parent_id as neo_pare2_2_0__,
        neochildon1_.id as id1_2_0__,
        neochildtw2_.neo_parent_id as neo_pare2_3_2_,
        neochildtw2_.neo_parent_id as neo_pare2_3_1__,
        neochildtw2_.id as id1_3_1__
    from
        neo_parent neoparent0_
    left outer join
        neo_child_one neochildon1_
            on neoparent0_.id=neochildon1_.neo_parent_id
    left outer join
        neo_child_two neochildtw2_
            on neoparent0_.id=neochildtw2_.neo_parent_id
NeoParent(id=1, neoChildOnes=[NeoChildOne(id=1), NeoChildOne(id=2)], neoChildTwos=[NeoChildTwo(id=1)])
NeoParent(id=2, neoChildOnes=[NeoChildOne(id=3)], neoChildTwos=[NeoChildTwo(id=3), NeoChildTwo(id=2)])

まとめ

  • 単純に@OneToManyをfindAllで取得すると複数回SQL投げてしまう
  • 1回のSQLで@OneToManyの要素を1種類取得したい場合は、JOIN FETCHで取得
  • 1回のSQLで@OneToManyの要素を複数種類取得したい場合は、MultipleBagFetchExceptionが発生してしまうため、List型ではなくSet型にしてJOIN FETCHで取得

IntelliJやGolandなどJetBrains製のIDEでProjectのファイルツリーを一括で開く方法

Projectのファイルツリーを表示する際に折り畳むのは一括でできるけれど、展開がマウスポチポチするしかわからなかったので調べてみました。

 

今回はGolandを使って説明します。

設定の変更

本来のキーマップ(テンキーを使ったショートカット)で使う場合はこの手順は必要ありません。

  1. [File]->[Settings]で設定を開く
    f:id:memo-pad:20180821215419p:plain
  2. Settingsウィンドウで[Keymap]を選択
    f:id:memo-pad:20180821215424p:plain
  3. 右側の検索ウィンドウにfullyと入力
    f:id:memo-pad:20180821215430p:plain
  4. [Fully Expand Tree Node]をダブルクリックするとメニューが表示されるので、[Add Keyboard Shortcut]を選択
    f:id:memo-pad:20180821215433p:plain
  5. Keyboard Shortcutで使いやすいショートカットを設定(今回はAlt+Aで使用できるように設定)
    f:id:memo-pad:20180821215435p:plain
  6. 設定を反映

ファイルツリーの展開方法

  1. 展開したいディレクトリを選択し、展開用のショートカットを実行
    f:id:memo-pad:20180821215444p:plain
  2. 1階層展開されるので、もう一度ショートカットを実行
    f:id:memo-pad:20180821215447p:plain
  3. 次の階層まで展開される
    (この時にはディレクトリの選択を変える必要はないので、一番最下層まで開きたい場合はショートカットを連打すれば良いです)
    f:id:memo-pad:20180821215450p:plain

Linux MintでWQHDのモニタをつなぐとフリーズしてしまうときの対策

TL;DL

  1. 最近のCPUならxserver-xorg-video-intelをアンインストール
    apt remove xserver-xorg-video-intel
  2. PCを再起動 

状況

  • Thinkpad x220でLinux Mintを使用
  • DisplayPortでWQHD(2560x1440)のディスプレイと接続
  • デフォルトでWUXGA(1920x1200)が選択される
  • ディスプレイ設定からWQHDを選択すると、デスクトップ環境(Cinnamon)がフリーズ

調査 

何が悪そうか
  • ディスプレイドライバの問題?
  • DisplayPortのケーブル自体の問題?
  • X220自体の問題?
  • Linux Mintの問題?
  • Cinnamon環境の問題?
一通り調べた結果
  • Linux Mintのissueに、それらしきissueがありました。

github.com

OK, we've got news on this and it's turning to be (at least) an upstream issue in the Intel driver. We've got both good news and bad news about this....

Bad news: This driver is no longer maintained so it's very unlikely this will get fixed.

Good news: This driver is only useful for really old Intel GPUs (10 year old and more... the likes of i800x, i915, i965) and it is not recommended for recent Intel GPUs. Instead, it is recommended to use modesetting, not only to avoid this freeze issue, but also to get better performance.

Anyhow, there are two solutions to this problem:

Solution 1 - Recommended for people with modern Intel GPUs (2007 and newer)

Remove the Intel driver to use modesetting instead:

apt remove xserver-xorg-video-intel

And then reboot the computer.

Solution 2 - Recommended for people with old Intel GPUs (i965, i915, i8xx..etc)

Disable VSync:

echo CLUTTER_VBLANK=none >> ~/.profile

And then log out.

日本語でざっくり

clefebvreさんのこの文章読むと、

  • このIntelのドライバ(xserver-xorg-video-intel)は10年以上前の古いIntel GPUのためのもので、最近のIntel GPUでは非推奨
  • 代わりに、modesettingを使うのが推奨されている
  • modesettingにすると、フリーズ問題を回避できるだけじゃなく、パフォーマンスもよくなる

というようなことが書いてあります。

対策

ということで、Solution1に書いてあるxserver-xorg-video-intelをアンインストール後、再起動というのを試してみました。

 

 再起動後にWQHDディスプレイに接続すると、前回と違って最初からWQHDがデフォルトで選択されており無事出力されました。

 

もし、同じような現象起こっている人がいれば、参考までにどうぞ。

PostgreSQLとPostGISで位置情報を使用する

現在地と近いデータ持ってくるのにPostgreSQLPostGISを使ったので、その時の構築メモ

現在地取得の仕方とかは書いてないです

環境

PostgreSQLインストール

$ wget https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm
$ sudo rpm -ivh pgdg-centos10-10-2.noarch.rpm
$ ls -l /etc/yum.repos.d/
-rw-r--r--  1 root root 1004 Sep 24 18:54 pgdg-10-centos.repo
$ sudo yum install postgresql-server --disablerepo=* --enablerepo=pgdg10
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Installed:
  postgresql10-server.x86_64 0:10.2-1PGDG.rhel7

Dependency Installed:
  postgresql10.x86_64 0:10.2-1PGDG.rhel7
  postgresql10-libs.x86_64 0:10.2-1PGDG.rhel7

Complete!

PostGISインストール

$ sudo yum install postgis24_10
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Installed:
  postgis24_10.x86_64 0:2.4.3-1.rhel7

Dependency Installed:
  CGAL.x86_64 0:4.7-1.rhel7
  CharLS.x86_64 0:1.0-5.el7
  SFCGAL.x86_64 0:1.2.2-1.rhel7
  SFCGAL-libs.x86_64 0:1.2.2-1.rhel7
  SuperLU.x86_64 0:5.2.0-5.el7
  armadillo.x86_64 0:8.300.0-1.el7
  arpack.x86_64 0:3.1.3-2.el7
  atk.x86_64 0:2.22.0-3.el7
  atlas.x86_64 0:3.10.1-12.el7
  avahi-libs.x86_64 0:0.6.31-17.el7
  blas.x86_64 0:3.4.2-8.el7
  boost-serialization.x86_64 0:1.53.0-27.el7
  cairo.x86_64 0:1.14.8-2.el7
  cfitsio.x86_64 0:3.370-10.el7
  cups-libs.x86_64 1:1.6.3-29.el7
  fontconfig.x86_64 0:2.10.95-11.el7
  fontpackages-filesystem.noarch 0:1.44-8.el7
  freexl.x86_64 0:1.0.4-1.el7
  gdal-libs.x86_64 0:1.11.4-12.rhel7
  geos36.x86_64 0:3.6.2-3.1.rhel7
  giflib.x86_64 0:4.1.6-9.el7
  graphite2.x86_64 0:1.3.10-1.el7_3
  gtk-update-icon-cache.x86_64 0:3.22.10-5.el7_4
  gtk2.x86_64 0:2.24.31-1.el7
  harfbuzz.x86_64 0:1.3.2-1.el7
  hdf5.x86_64 0:1.8.12-10.el7
  hicolor-icon-theme.noarch 0:0.12-7.el7
  lapack.x86_64 0:3.4.2-8.el7
  lcms2.x86_64 0:2.6-3.el7
  libICE.x86_64 0:1.0.9-9.el7
  libSM.x86_64 0:1.2.2-2.el7
  libXcomposite.x86_64 0:0.4.4-4.1.el7
  libXcursor.x86_64 0:1.1.14-8.el7
  libXdamage.x86_64 0:1.1.4-4.1.el7
  libXext.x86_64 0:1.3.3-3.el7
  libXfixes.x86_64 0:5.0.3-1.el7
  libXft.x86_64 0:2.3.2-2.el7
  libXi.x86_64 0:1.7.9-1.el7
  libXinerama.x86_64 0:1.1.3-2.1.el7
  libXrandr.x86_64 0:1.5.1-2.el7
  libXrender.x86_64 0:0.9.10-1.el7
  libXxf86vm.x86_64 0:1.1.4-1.el7
  libaec.x86_64 0:1.0.2-1.el7
  libdap.x86_64 0:3.13.1-2.el7
  libgeotiff.x86_64 0:1.4.0-1.rhel7
  libgfortran.x86_64 0:4.8.5-16.el7_4.1
  libgta.x86_64 0:1.0.4-1.el7
  libquadmath.x86_64 0:4.8.5-16.el7_4.1
  libthai.x86_64 0:0.1.14-9.el7
  libtool-ltdl.x86_64 0:2.4.2-22.el7_3
  libwebp.x86_64 0:0.3.0-7.el7
  libxshmfence.x86_64 0:1.2-1.el7
  libxslt.x86_64 0:1.1.28-5.el7
  lyx-fonts.noarch 0:2.2.3-1.el7
  mesa-libEGL.x86_64 0:17.0.1-6.20170307.el7
  mesa-libGL.x86_64 0:17.0.1-6.20170307.el7
  mesa-libGLU.x86_64 0:9.0.0-4.el7
  mesa-libgbm.x86_64 0:17.0.1-6.20170307.el7
  mesa-libglapi.x86_64 0:17.0.1-6.20170307.el7
  mpfr.x86_64 0:3.1.1-4.el7
  netcdf.x86_64 0:4.3.3.1-5.el7
  ogdi.x86_64 0:3.2.0-4.rhel7
  openblas-openmp.x86_64 0:0.2.20-3.el7
  openjpeg-libs.x86_64 0:1.5.1-17.el7
  openjpeg2.x86_64 0:2.1.0-7.el7
  pango.x86_64 0:1.40.4-1.el7
  pixman.x86_64 0:0.34.0-1.el7
  poppler.x86_64 0:0.26.5-17.el7_4
  poppler-data.noarch 0:0.4.6-3.el7
  postgresql10-contrib.x86_64 0:10.2-1PGDG.rhel7
  proj49.x86_64 0:4.9.3-3.rhel7
  unixODBC.x86_64 0:2.3.1-11.el7
  xerces-c.x86_64 0:3.1.1-8.el7_2

Complete!

PostgreSQL+PostGISでサンプル実行

準備

$ sudo /usr/pgsql-10/bin/postgresql-10-setup initdb
Initializing database ... OK
$ sudo systemctl start postgresql-10
  • postgresユーザになり、DBに接続
$ sudo su postgres

$ psql -U postgres
could not change directory to "/root": Permission denied
psql (10.2)
Type "help" for help.
  • テスト用DBを作成
postgres=# CREATE DATABASE test;
CREATE DATABASE
  • テスト用DBに接続
postgres=# \connect test
You are now connected to database "test" as user "postgres".
  • PostGISが有効になっていることを確認
test=# CREATE EXTENSION postgis;
CREATE EXTENSION

test=# select PostGIS_full_version();
                                                                                postgis_full_version

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 POSTGIS="2.4.3 r16312" PGSQL="100" GEOS="3.6.2-CAPI-1.10.2 4d2925d6" PROJ="Rel. 4.9.3, 15 August 2016" GDAL="GDAL 1.11.4, released 2016/01/25" LIBXML="2.9.1" LIBJSON="0.11" RASTER
(1 row)

サンプルの実行

  • サンプル用のテーブル作成
postgres=# \connect test
You are now connected to database "test" as user "postgres".
test=# CREATE TABLE locations
test-# (
test(#   id bigserial NOT NULL,
test(#   name character varying(128) NOT NULL,
test(#   "position" geometry,
test(#   CONSTRAINT id PRIMARY KEY (id)
test(# )
test-# WITH (
test(#   OIDS=FALSE
test(# );
CREATE TABLE

(コピペ用)

CREATE TABLE locations
(
  id bigserial NOT NULL,
  name character varying(128) NOT NULL,
  "position" geometry,
  CONSTRAINT id PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
  • データの挿入(POINTは経度Lon 緯度Latの順番なので注意)
test=# INSERT INTO locations (id, name, position) VALUES (1, '東京駅', ST_GeomFromText('POINT(139.767052 35.681167)', 4326));
INSERT 0 1
test=# INSERT INTO locations (id, name, position) VALUES (2, '大阪駅', ST_GeomFromText('POINT(135.495951 34.702485)', 4326));
INSERT 0 1
test=# INSERT INTO locations (id, name, position) VALUES (3, '名古屋駅', ST_GeomFromText('POINT(136.906398 35.181446)', 4326));
INSERT 0 1
  • 博多駅(130.420611 33.590045)から近い順でデータを取得
test=# SELECT * FROM locations ORDER BY ST_DistanceSphere(position, ST_GeomFromText('POINT(130.420611 33.590045)', 4326)) OFFSET 0 LIMIT (5);
 id |   name   |                      position
----+----------+----------------------------------------------------
  2 | 大阪駅   | 0101000020E610000064ADA1D4DEEF60401D774A07EB594140
  3 | 名古屋駅 | 0101000020E61000001DE56036011D6140B9FE5D9F39974140
  1 | 東京駅   | 0101000020E61000009BCAA2B08B786140A60EF27A30D74140
(3 rows)

(補足)postgresユーザ以外からでもパスワードで接続できるように設定変更

$ sudo su postgres -c 'psql --username=postgres'
could not change directory to "/home/user": 許可がありません
psql (10.1)
Type "help" for help.
  • DBユーザのパスワード設定
postgres=# ALTER USER postgres with encrypted password 'postgres';
ALTER ROLE

postgres-# \q
  • pg_hba.confの設定を追加
$ sudo vim /var/lib/pgsql/10/data/pg_hba.conf

# 下記を他の設定より上に追加
local   all             postgres                                md5
host    all             postgres        127.0.0.1/32            md5
host    all             postgres        ::1/128                 md5

(追記後はこんな感じ)

# TYPE  DATABASE        USER            ADDRESS                 METHOD

local   all             postgres                                md5
host    all             postgres        127.0.0.1/32            md5
host    all             postgres        ::1/128                 md5
# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            ident
host    replication     all             ::1/128                 ident
  • 設定反映のためにPostgreSQLをリスタート
$ sudo systemctl restart postgresql-10
  • postgresqlユーザ以外からパスワード認証で接続できることを確認
psql -U postgres -h localhost -W

Visual Studio Codeでリモートサーバのファイルを編集する

今回使ったのはこちらのRemote VSCode marketplace.visualstudio.com

今回の環境

  • ローカル
linux mint 18.1
Visual Studio Code 1.16.1
Remote VSCode 1.1.0
  • リモート
ubuntu 16.04
rmate 1.0.0 (shell script版)

ローカルの設定

Remote VSCodeのインストール

  1. Visual Studio CodeでCtrl-pを押し、ext install remote-vscodeと入力後、Enter f:id:memo-pad:20171008210225p:plain

  2. 拡張機能の検索結果が表示されるので、Remote VSCodeをインストール f:id:memo-pad:20171008210229p:plain

  3. 拡張機能を再読み込みさせRemote VSCodeを有効化 f:id:memo-pad:20171008210232p:plain

Remote VSCodeの設定変更

  1. 「ファイル」-「基本設定」-「設定」からユーザ設定を開く f:id:memo-pad:20171008210235p:plain

  2. ユーザ設定のRemote VSCode Configurationが下記のような値になっているので、remote.onstartuptrueに変更する f:id:memo-pad:20171008210238p:plain f:id:memo-pad:20171008210240p:plain

Remote VSCode用のsshトンネルを作成

  1. 端末でリモートサーバとのssh tunnelを作成する
ssh -R 52698:127.0.0.1:52698 [リモートサーバのユーザ名]@[リモートサーバのホスト]

リモートの設定

今回はruby版ではなく、shell script版を利用する github.com

rmateのインストール

  1. rmateをダウンロードし、実行権限を付与
sudo wget -O /usr/local/bin/rmate https://raw.github.com/aurora/rmate/v1.0.0/rmate
sudo chmod a+x /usr/local/bin/rmate
  • 補足:最新版を入れるなら下記コマンド
sudo wget -O /usr/local/bin/rmate https://raw.github.com/aurora/rmate/master/rmate

rmateの実行

  1. リモートサーバで下記コマンドを実行すると、ローカルのVisual Studio Codeで指定したファイルが表示される
rmate -p 52698 [編集したいファイル名]
  • 注意
    • リモートサーバとのsshトンネルが切れていると失敗します
    • ローカル側でVisual Studio Codeを事前に立ち上げておかないと失敗します

更新の同期方法

ローカルでの更新内容をリモートに同期

  1. Visual Studio Codeで更新したファイルを保存するだけ

リモートでの更新内容をローカルに同期

  1. リモートのファイルを編集するときと同じ
rmate -p 52698 [更新したファイル名]