Azure DevOps Pipelines: pr: none を明示しないと、PR作成時に、意図せず Pipeline が動いてしまう

  • デフォルトで生成される azure-pipelines.yml は以下
    • 注意点
      • pr: none が明示されていなので、PR作成時に Pipeline が動く
trigger:
- main

pool:
  vmImage: ubuntu-latest
steps:
- script: echo Hello, world!
  displayName: 'Run a one-line script'
- script: |
    echo Add other tasks to build, test, and deploy your project.
    echo See https://aka.ms/yaml
  displayName: 'Run a multi-line script'

検証用リポジトリ

https://github.com/tamurayk/azure_devops_pipeline_test

CakePHP4.x: hasMany の Association を contain すると 別SQL になる仕組み

version

仕組み

// 流れ
\Cake\Database\Driver::prepare
  \Cake\ORM\Query::sql
    \Cake\ORM\Query::_transformQuery
      \Cake\ORM\EagerLoader::attachAssociations
        \Cake\ORM\EagerLoader::attachableAssociations
          \Cake\ORM\EagerLoader::_resolveJoins

理解できていない事

  • hasMany の Association を contain した場合は、別SQLにする、という設計になっている理由 (設計思想)

作業ログ

以下のような Learning Test を書いて、デバッグした

    /**
     * @group leaning
     */
    public function testHasMany(): void
    {
      //..

      $query = $ArticlesTable->find();

      // Articles belongsTo Authors
      // Articles hasMany Comments
      $query->contain(['Authors', 'Comments']);
      $result_set = $query->all();

      // ...
    }

デバッグログ

// Leaning Test 内で \Cake\ORM\Query::all を実行
string(17) "get_class($query)"
string(14) "Cake\ORM\Query"
string(54) "↓ \Cake\ORM\Query::all $this->getRepository()::class"
  string(28) "App\Model\Table\ArticlesTable"
  string(69) "↓↓ \Cake\Datasource\QueryTrait::all $this->getRepository()::class"
    string(28) "App\Model\Table\ArticlesTable"
      string(65) "↓↓↓ \Cake\ORM\Query::_execute $this->getRepository()::class"
      string(28) "App\Model\Table\ArticlesTable"
      string(121) "!!!!!!!! \Cake\ORM\Query::_execute | $statement = $this->getEagerLoader()->loadExternal($this, $this->execute()) !!!!!!!!"
        string(72) "↓↓↓↓ \Cake\Database\Query::execute $this->getRepository()::class"
          string(28) "App\Model\Table\ArticlesTable"
          string(30) "\Cake\Database\Connection::run"
          string(34) "\Cake\Core\Retry\CommandRetry::run"
          string(43) "\Cake\Database\Connection::run の callback"
          string(34) "\Cake\Database\Connection::prepare"
          string(34) "\Cake\Core\Retry\CommandRetry::run"
          string(47) "\Cake\Database\Connection::prepare の callback"
          string(34) "\Cake\Database\Driver::prepare (1)"
          string(38) "\Cake\Database\Driver::prepare (2) sql"
          string(1134) "SELECT ... FROM Articles Articles INNER JOIN Authors Authors ON (Authors.id = (Articles.author_id))"
          string(60) "\Cake\Database\Driver::prepare (end) return new PDOStatement"
        string(121) "↑↑↑↑ \Cake\Database\Query::execute (end) return \Cake\Database\StatementInterface | $this->getRepository()::class"
        string(28) "App\Model\Table\ArticlesTable"
        string(83) "↓↓↓↓↓ \Cake\ORM\EagerLoader::loadExternal  $query->getRepository()::class"
          string(28) "App\Model\Table\ArticlesTable"
          string(81) "\Cake\ORM\EagerLoader::loadExternal (2) $external is not empty | count($external)"
          int(1)
          string(68) "\Cake\ORM\EagerLoader::loadExternal (3) foreach ($external as $meta)"
          string(62) "\Cake\ORM\EagerLoader::loadExternal (3-1) ※foreach内 $alias"
          string(7) "Articles"
          string(54) "↓ \Cake\ORM\Query::all $this->getRepository()::class"
            string(26) "App\Model\Table\CommentsTable"
            string(69) "↓↓ \Cake\Datasource\QueryTrait::all $this->getRepository()::class"
              string(26) "App\Model\Table\CommentsTable"
              string(65) "↓↓↓ \Cake\ORM\Query::_execute $this->getRepository()::class"
                string(26) "App\Model\Table\CommentsTable"
                string(121) "!!!!!!!! \Cake\ORM\Query::_execute | $statement = $this->getEagerLoader()->loadExternal($this, $this->execute()) !!!!!!!!"
                  string(72) "↓↓↓↓ \Cake\Database\Query::execute $this->getRepository()::class"
                    string(26) "App\Model\Table\CommentsTable"
                    string(30) "\Cake\Database\Connection::run"
                    string(34) "\Cake\Core\Retry\CommandRetry::run"
                    string(43) "\Cake\Database\Connection::run の callback"
                    string(34) "\Cake\Database\Connection::prepare"
                    string(34) "\Cake\Core\Retry\CommandRetry::run"
                    string(47) "\Cake\Database\Connection::prepare の callback"
                    string(34) "\Cake\Database\Driver::prepare (1)"
                    string(38) "\Cake\Database\Driver::prepare (2) sql"
                    string(399) "SELECT ... FROM Comments Comments WHERE Comments.article_id in (:c0)"
                    string(60) "\Cake\Database\Driver::prepare (end) return new PDOStatement"
                  string(121) "↑↑↑↑ \Cake\Database\Query::execute (end) return \Cake\Database\StatementInterface | $this->getRepository()::class"
                  string(26) "App\Model\Table\CommentsTable"
                  string(83) "↓↓↓↓↓ \Cake\ORM\EagerLoader::loadExternal  $query->getRepository()::class"
                    string(26) "App\Model\Table\CommentsTable"
                  string(78) "↑↑↑↑↑ \Cake\ORM\EagerLoader::loadExternal (1-end) $external is empty"
              string(113) "↑↑↑ \Cake\ORM\Query::_execute (end) return new ResultSet($this, $statement) | $this->getRepository()::class"
              string(26) "App\Model\Table\CommentsTable"
            string(120) "↑↑ \Cake\Datasource\QueryTrait::all (end) return \Cake\Datasource\ResultSetInterface | $this->getRepository()::class"
            string(26) "App\Model\Table\CommentsTable"
            string(106) "↑ \Cake\ORM\Query::all (end) return \Cake\Datasource\ResultSetInterface | $this->getRepository()::class "
          string(26) "App\Model\Table\CommentsTable"
          string(126) "\Cake\ORM\EagerLoader::loadExternal (3-end) ※foreach内 $statement = new CallbackStatement($statement, $driver, $f) | $alias"
          string(7) "Articles"
        string(98) "↑↑↑↑↑ \Cake\ORM\EagerLoader::loadExternal (end) return \Cake\Database\StatementInterface"
      string(113) "↑↑↑ \Cake\ORM\Query::_execute (end) return new ResultSet($this, $statement) | $this->getRepository()::class"
    string(28) "App\Model\Table\ArticlesTable"
  string(120) "↑↑ \Cake\Datasource\QueryTrait::all (end) return \Cake\Datasource\ResultSetInterface | $this->getRepository()::class"
  string(28) "App\Model\Table\ArticlesTable"
string(106) "↑ \Cake\ORM\Query::all (end) return \Cake\Datasource\ResultSetInterface | $this->getRepository()::class "
string(28) "App\Model\Table\ArticlesTable"

今後の学習テーマ

  • hasManyのTableをSearchプラグインで検索する際の問題点と対応

  • note

    • contain すると 別SQL になる為、beforeProcessでJOINする必要がある
    • 意図した検索結果を得るには ID で DISTINCTする必要がある
    • ID 以外で ORDER BY したい
      • DISTINCT で指定したカラムでしか ORDER BY できない

Intel Mac から M1 Mac に移行後、Alfredでファイル検索ができない問題の解消方法

Version

what

  • Intel Mac から M1 Mac移行アシスタント + ターゲットディスクモード で移行した
  • 移行後、Alfred でファイル検索が出来なくなった

解決方法

  • spotlights の インデックス を再構築

再構築方法

  1. sudo mdutil -E /
  2. spotlights で何らかのを検索 => 索引作成中... と表示され、インデックスの再構築が行われる (時間かかる)

メモ

  • Alfred は spotlights の インデックス に依存している

PDO と プリペアドステートメント(使用|未使用)時のデータ取得の流れ

ドキュメント

note

参考になったエントリー

CakePHP 4.x: DBのデータ型 から PHPの型(Entityのpropertyの型) へのCast

DBのデータ型 から PHPの型(Entityのpropertyの型) への変換

PHPの型(Entityのpropertyの型) から DBのデータ型 への変換

GIN Index についての覚書

GIN Index

解決したい問題 / 解決方法

note

  • 部分一致 検索にも対応

注意点

  • GINインデックスの更新は低速になりがち

Gist index vs GIN index

GINインデックスは検索が高速なので、静的なデータにもっとも向いている

  • Gist index

    • 動的なデータに向いている
    • 非可逆 (間違った結果を返すかもしれない)
  • GIN index

    • 静的なデータに向いている
    • (標準の問い合わせに対しては) 可逆

    • メリット

      • 検索
        • GiSTの約3倍高速
    • デメリット
      • インデックスの構築
        • GiSTの約3倍時間がかかります
      • 更新
        • GiSTよりも非常に低速

Azure Functions: `Azure Functions Core Tools` で TypeScript/QueueTrigger の関数を `func start` 時に `Value cannot be null. (Parameter 'provider')` エラー

バージョン

  • OS: macOS Catalina 10.15.7
  • Azure Functions Core Tools: 3.0.3785
  • node: 14.17.5

遭遇したエラー

Value cannot be null. (Parameter 'provider')

$ func start

Azure Functions Core Tools
Core Tools Version:       3.0.3785 Commit hash: db6fe71b2f05d09757179d5618a07bba4b28826f  (64-bit)
Function Runtime Version: 3.2.0.0

[2021-10-01T13:16:19.680Z] Cannot create directory for shared memory usage: /dev/shm/AzureFunctions
[2021-10-01T13:16:19.680Z] System.IO.FileSystem: Access to the path '/dev/shm/AzureFunctions' is denied. Operation not permitted.
[2021-10-01T13:16:20.590Z] A host error has occurred during startup operation '974818a2-159a-4925-a571-4d4330134e2b'.
[2021-10-01T13:16:20.590Z] Microsoft.Azure.WebJobs.Script: Did not find functions with language [node].
Value cannot be null. (Parameter 'provider')

エラー原因

  • yarn build せずに func start していた

  • function.json を下記のように設定し func start
//function.json
{
  //...
  "scriptFile": "../QueueTrigger/index.ts"
}

  • function.json を下記のように設定し、yarn build 後に func start
{
  //...
  "scriptFile": "../dist/QueueTrigger/index.js"
}

ハマった事

  • Value cannot be null. (Parameter 'provider') についてはいくつも issue が上がっており、総じて ExtensionBundle 起因するエラー、解消方法は、host.json から extensionBundle を削除、というものだった。

  • 今回のケースでは ExtensionBundle とは関連はなかった にも関わらず、上記の issue で示されている work around で試行錯誤してしまった。

解決のきっかけ

  • JavaScript/QueueTrigger ではエラーにならなかった為、index.ts に起因するエラーではないか、とあたりがついた。