end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

TortoiseGitで repository path 'X:/tmp/saawo/' is not owned by current user エラー

wslで起動した oracle linuxをsambaで Xドライブをマウントし、 そこに TortoiseGitで git cloneし、commit等を行ったところ、以下のエラーが発生

---------------------------
TortoiseGit
---------------------------
Could not get HEAD hash.
libgit2 returned: repository path 'X:/tmp/???/' is not owned by current user.

To add an exception for this directory, call:
git config --global --add safe.directory 'X:/tmp/???'
---------------------------
OK   
---------------------------

ダイアログに 「git config --global --add safe.directory 'X:/tmp/???'」とありますので、 TortoiseGitの設定から「Edit global .gitconfig」を開き、 ドライブ名を「x→X」のように大文字にすることで解消

[safe]
directory = x            ##★ ココ
directory = x:/tmp/???   ##★ ココ
directory = %(prefix)///172.18.129.236/end0tknr/tmp/??? ##★ ココ
directory = 'x:/tmp/???' ##★ ココ

emacs 27 for windows への jedi(python 自動補完)の install

ポイントは

  • minicondaをinstallし、windowsのPATHを通す
  • pip installで jediに加え、virtualenv もインストール

かと思います。

step1 - miniconda (python11)の install

2024/3時点で、minicondaの最新は python12版ですが、 emacsのjediが対応していない為、python11版をinstall。

その上で、windows環境変数 PATHに以下を追加

  • c:\Users\end0t\AppData\Local\miniconda3
  • c:\Users\end0t\AppData\Local\miniconda3\Scripts

step2 - pip install jedi & virtualenv

(conda base)> pip install jedi
(conda base)> pip install virtualenv

step3 - emacs package install

https://monologu.com/add-melpa/ を参考に、init.el へ以下を追記

(when (require 'package nil t)
  (add-to-list 'package-archives
     '("melpa" .      "http://melpa.org/packages/"))
  (package-initialize))

その上で、

  • M-x package-install jedi
  • M-x jedi:install-server

step4 - emacs の init.el に jediの設定

https://tkf.github.io/emacs-jedi/latest/ を参考に以下を追記

(add-hook 'python-mode-hook 'jedi:setup)
(setq jedi:complete-on-dot t)

すると、*.py ファイルの編集時、以下のように自動補完されます

requests for python による大容量レスポンスの分割ダウンロード

requests for python で、巨大なfileをhttp getする場合、stream=True で chunk化 - end0tknr's kipple - web写経開発

以前の上記entryの修正版です。

国土交通省で公開している不動産取引価格情報取得API ( https://www.land.mlit.go.jp/webland/api.html )に対し、 python3標準の urllib.request を用い

import urllib.request
http_conf = {"retry_limit":3, "retry_sleep":5 }

def get_http_requests(self, req_or_url,req_timeout=5):
    i = 0
    while i < http_conf["retry_limit"]:
        i += 1
        try:
            http_res = urllib.request.urlopen(req_or_url, timeout=req_timeout)
            html_content = http_res.read()
            return html_content
        
        except Exception as e:
            if "404: Not Found" in str(e):
                logger.error("{} {}".format(req_or_url, e))
                return None
            
            logger.warning(e)
            logger.warning("retry {} {}".format(i,req_or_url))
            time.sleep(http_conf["retry_sleep"])

    return None

のように http getを行うと、本来、数MBの要領がある影響でしょうか、 レスポンスが途中で途切れてしまいます。

https://docs.python.org/ja/3/library/urllib.request.html を見ると、 「 より高水準のHTTPクライアントインターフェースとして Requestsパッケージ がお奨めです。」 という記載がありましたので、

「pip install requests」した上で、以下のように requests を用い、かつ、「stream=True」で分割ダウンロードすることで解消

import requests

def get_http_requests(self,req_url):
    i = 0
    while i < 3: # 最大3回 retry
        i += 1
        try: # 先方サーバによっては http response codeを返さない為、try-except
            res = requests.get(req_url, timeout=(5,60), stream=True)
        except Exception as e:
            logger.warning(e)
            logger.warning("retry {} {}".format(i,req_url))
            time.sleep(10)

        if res.status_code == 404:
            logger.error( "404 error {}".format(req_url) )
            return

        try:
            res.raise_for_status()
        except Exception as e:
            logger.warning(e)
            logger.warning("retry {} {}".format(i,req_url))
            time.sleep(10)

    # 大容量の為か urllib.request.urlopen()では
    # response contentを取得できなかった為、stream=True で chunk化
    chunks = []
    for chunk in res.iter_content(chunk_size=1024*1024):
        chunks.append(chunk)
      
    content = b"".join(chunks).decode()
    return json.loads( content )

Oracle Linux 8.7 への日本語フォント インストール

$ sudo yum install ipa-gothic-fonts ipa-mincho-fonts \
                   ipa-pgothic-fonts ipa-pmincho-fonts

以前、centosに対しては上記のようにipaのフォントをインストールしていましたが、 redhat?には、このフォントがないみたい。

なので、以下

$ sudo yum search japan font
Repository google-chrome is listed more than once in the configuration
Last metadata expiration check: 4:46:37 ago on Thu Mar 21 02:47:33 2024.
======================== Summary & Name Matched: japan, font ========================
adobe-source-han-sans-jp-fonts.noarch : Adobe OpenType Pan-CJK font family for
                                      : Japanese
adobe-source-han-sans-jp-fonts.src : Adobe OpenType Pan-CJK font family for Japanese
google-noto-sans-cjk-jp-fonts.noarch : Japanese Multilingual Sans OTF font files for
                                     : google-noto-cjk-fonts
vlgothic-fonts.noarch : Japanese TrueType font
vlgothic-fonts.src : Japanese TrueType font
vlgothic-p-fonts.noarch : Proportional Japanese TrueType font
=========================== Summary Matched: japan, font ============================
texlive-wadalab.noarch : Wadalab (Japanese) font packages
$ sudo yum install \
  adobe-source-han-sans-jp-fonts \
  google-noto-sans-cjk-jp-fonts \
  vlgothic-fonts.noarch \
  vlgothic-p-fonts

install postgres 16.2 from source to Oracle Linux 8.7

install postgres 14.1 from source to cent 7.9 - end0tknr's kipple - web写経開発

上記entryまでは、virtual box上のcentosにinstallしていましたが、 今回は、wsl(Windows Subsystem for Linux)上の Oracle Linuxへ、インストール

$ cat /etc/redhat-release 
Red Hat Enterprise Linux release 8.7 (Ootpa)

$ cat /etc/os-release 
NAME="Oracle Linux Server"
VERSION="8.7"
ID="ol"
ID_LIKE="fedora"
VARIANT="Server"
VARIANT_ID="server"
VERSION_ID="8.7"
PLATFORM_ID="platform:el8"
PRETTY_NAME="Oracle Linux Server 8.7"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:oracle:linux:8:7:server"
HOME_URL="https://linux.oracle.com/"
BUG_REPORT_URL="https://bugzilla.oracle.com/"

ORACLE_BUGZILLA_PRODUCT="Oracle Linux 8"
ORACLE_BUGZILLA_PRODUCT_VERSION=8.7
ORACLE_SUPPORT_PRODUCT="Oracle Linux"
ORACLE_SUPPORT_PRODUCT_VERSION=8.7

依存libraryのinstall

$ sudo yum install libicu-devel
$ sudo yum install readline-devel
$ sudo yum install zlib-devel
$ sudo yum install systemd-devel

postgresのinstall

$ wget --no-check-certificate \
  https://ftp.postgresql.org/pub/source/v16.2/postgresql-16.2.tar.gz

$ tar -xvf postgresql-16.2.tar.gz
$ cd postgresql-16.2
$ less INSTALL

$ ./configure --with-systemd
$ make
$ make check
$ sudo su
# make install
# adduser postgres
# mkdir /usr/local/pgsql/data
# chown postgres /usr/local/pgsql/data

postgresの設定?

# su - postgres
$ /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
$ /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -l logfile start

$ /usr/local/pgsql/bin/createdb test
$ /usr/local/pgsql/bin/psql test

自動起動

$ sudo vi /etc/systemd/system/postgresql.service

[Unit]
Description=PostgreSQL database server
Documentation=man:postgres(1)

[Service]
Type=notify
User=postgres
ExecStart=/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
KillSignal=SIGINT
TimeoutSec=0

[Install]
WantedBy=multi-user.target

$ sudo systemctl enable postgresql
Created symlink /etc/systemd/system/multi-user.target.wants/postgresql.service → /etc/systemd/system/postgresql.service.
$ sudo systemctl start postgresql

csvを含むzipをjszip+papaparse for javascriptで読み sql.js で sql select

sql.js によるブラウザでの sqlite3 操作 - end0tknr's kipple - web写経開発

先日の上記entryでは sql.js で sqlite3のバイナリファイルを扱いましたが、 今回は、csvを含むzipをjszip+papaparse for javascriptで読み、sql.js で sql select

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.2/sql-wasm.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.4.1/papaparse.min.js"></script>
<script src="./csv_db.js"></script>
</head>
<body>
  <button onclick="csv_db.load_csv_zip()">CSV-ZIP選択</button>
  <button onclick="csv_db.select_tbl()">SQL SELECT * FROM $TABLE</button>
  <div id="sql_result"></div>
  
  <script>let csv_db = new CsvDb();</script>
</body>
</html>
'use strict';

class CsvDb {
    constructor() {}
    
    async load_csv_zip() {
        // windowsのコモン・ダイアログ?で zipを開く
        let zip_contents = await this.open_file_picker()
        // jpzipで zipを解凍
        let zip = new JSZip()
        await zip.loadAsync( zip_contents.arrayBuffer() )

        const SQL = await initSqlJs({
            locateFile:file=>
            `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.2/${file}`
        })
        this.db = new SQL.Database()
        this.table_names = []
        
        let csv_datas = []
        // zip に含まれる csv or tsv毎に処理
        for (const filename in zip.files) {
            const zip_content = zip.files[filename]
            if( zip_content.dir ) continue
            
            let parsed_filename = this.parse_csv_filename( filename )
            let tbl_name = parsed_filename[0]
            let csv_rows_str = await zip_content.async('text')
            // papa parseで csv or tsvをパース
            // https://www.papaparse.com/docs
            let tbl_rows   = Papa.parse(csv_rows_str.trim(),{delimiter:"\t"}).data
            let tbl_header = tbl_rows.shift()

            if(tbl_name=="planed_zumens") continue
            if(tbl_rows.length==0) continue
            // sql.jsに対し csv or tsv毎に create table, insert
            let sql_create =
                `CREATE TABLE  ${tbl_name}(${tbl_header.map(h=>`${h} TEXT`).join(',')});`
            let sql_insert =
                `INSERT INTO ${tbl_name}(${tbl_header.join(',')})
VALUES ${tbl_rows.map(r=>`(${r.map(r=>`'${r}'`).join(',')})`).join(',')};`
            this.db.run(sql_create).run(sql_insert)
            this.table_names.push(tbl_name)
        }

        document.querySelector("#sql_result").innerHTML =
            "読み込み完了. " + this.table_names.join(" ")

    }

    parse_csv_filename( org_filename ){
        let re_patern = /([^\./]+)\.(csv|tsv)$/i
        let re_result = re_patern.exec(org_filename)
        if(! re_result) return []

        let basename = re_result[1]
        let ext      = re_result[2]
        return [basename, ext]
    }
    
    // https://qiita.com/lumis/items/dd209d52c9bc7ce39db6
    async open_file_picker() {
        const pick_opts = {
            types      : [{description: "CSVを含むZIP",
                           accept:{'application/zip': ['.zip']} } ],
            multiple   : false,
            excludeAcceptAllOption: true }
        //「excludeAcceptAllOption: true 」は
        //「すべてのファイル (*.*)」の選択を無効にし
        // types に指定したファイルのみ選択okにする
        
        const [fh] = await showOpenFilePicker(pick_opts)
        const file = await fh.getFile()
        return file
    }

    select_tbl(){
        let tbl_name = this.table_names[1]
        let sql = `
SELECT * from ${tbl_name}
limit 10`;
        const stmt = this.db.prepare(sql);
        stmt.bind();
        let sql_result = "";
        while( stmt.step() ) {
            let row = stmt.getAsObject();
            sql_result += JSON.stringify(row);
        }
        document.querySelector("#sql_result").innerHTML = sql_result;
    }
}

pythonにおける csv ファイルのメール添付送信

code snippet ですが、少々の修正で、動作すると思います

#!python
# -*- coding: utf-8 -*-
from email.mime.text        import MIMEText
from email.mime.multipart   import MIMEMultipart
from email.mime.application import MIMEApplication
import csv
import io
import smtplib
import socket

CONF={
    "mail": {"smtp_server" : "xxx.xmile.sexy.co.jp",
             "port"    : 587,
             "user_id" : "ないしょ",
             "user_pw" : "ないしょ",
             "from"    : "ないしょ@example.com",
             "to"      : ["ないしょ@example.com"],
             "cc"      : [],
             },
}


def main():
    csv_for_espis = <省略>
    
    # 実fileに書き込まず、CSV添付する為、StringIO()を利用
    dummy_csv_file = io.StringIO()
    
    csv_headers = [
        "UserD","氏名","所属部所コード","日付","曜日",
        "入室時刻","退室時刻","最新入室時刻",
        "所属部所名","入室回数","退室回数" ]
    writer = csv.DictWriter(dummy_csv_file,
                            fieldnames=csv_headers)
    writer.writeheader()
    writer.writerows(csv_for_espis)
    csv_data = dummy_csv_file.getvalue()
    io.StringIO().close()

    # windows用csvの為、文字コードは cp932
    csv_data = csv_data.encode("cp932","ignore")

    # メール添付で送信
    notify_by_email( csv_data )
    
    logger.info("DONE "+func_name)


def notify_by_email(start_end_csv_contents):

    message = MIMEMultipart()
    message["Subject"] = "連携CSVデータ"
    message["From"]    = CONF["mail"]["from"]
    
    msg_body_tmpl = """e-SPIS の ご担当者様へ

※このメールは {hostname} {ip} にある
   RPA ({script}) から自動送信しています

連携用CSVを添付致しますので、ご確認をお願いします。

--
ないしょの署名
"""
    msg_body = msg_body_tmpl.format(
        hostname = socket.gethostname(),
        ip       = socket.gethostbyname(socket.gethostname()),
        script   = __file__ )

    message.attach( MIMEText(msg_body,"plain", "utf-8") )

    attachment = MIMEApplication(start_end_csv_contents)
    attachment.add_header("Content-Disposition", "attachment",
                          filename="E_SPIS_WORK.CSV" )
    message.attach( attachment )

    tos = []
    for mailto in CONF["mail"]["to"]:
        tos.append(mailto)

    if len(tos) == 0 :
        return

    to_addrs = tos
    
    message["To"]   = ",".join(tos)
    message["Cc"]   = ",".join( CONF["mail"]["cc"] )
    to_addrs += CONF["mail"]["cc"]
        
    try:
        server = smtplib.SMTP(CONF["mail"]["smtp_server"], CONF["mail"]["port"])
        #server.set_debuglevel(True)
        server.login( CONF["mail"]["user_id"], CONF["mail"]["user_pw"])
        server.send_message( message, to_addrs=to_addrs )
    except Exception as e:
        print(e)
    server.quit()
    


if __name__ == '__main__':
    main()

sql.js によるブラウザでの sqlite3 操作

web assemblyのおかげでしょうか、 最近は javascriptで sqlite3 のデータベースファイルを そのまま扱えるらしい。

参考url

install sqlite3

DOS> wsl

$ cat /etc/redhat-release
Red Hat Enterprise Linux release 8.7 (Ootpa)

$ sudo yum install sqlite

$ /usr/bin/sqlite3 --version
3.26.0 2018-12-01 12:34:55 bf8c1b2b7a5960c282e<略>38alt1

create ddl

-- 教師
DROP TABLE IF EXISTS teachers;
CREATE TABLE teachers ( teacher_id   BIGINT PRIMARY KEY,
                        teacher_name VARCHAR(64) );
INSERT INTO teachers VALUES (101,'先生一郎');
INSERT INTO teachers VALUES (102,'先生二郎');
INSERT INTO teachers VALUES (103,'先生三郎');

-- 学生
DROP TABLE IF EXISTS students;
CREATE TABLE students ( student_id BIGINT PRIMARY KEY,
                        student_name VARCHAR(64) );
INSERT INTO students VALUES (301,'生徒一子');
INSERT INTO students VALUES (302,'生徒二子');
INSERT INTO students VALUES (303,'生徒三子');
INSERT INTO students VALUES (304,'生徒四子');
INSERT INTO students VALUES (305,'生徒五子');
INSERT INTO students VALUES (306,'生徒六子');
INSERT INTO students VALUES (307,'生徒七子');
INSERT INTO students VALUES (308,'生徒八子');
INSERT INTO students VALUES (309,'生徒九子');

-- 講座
DROP TABLE IF EXISTS courses;
CREATE TABLE courses (
  course_id   VARCHAR(16)  PRIMARY KEY,
  course_name VARCHAR(128) NOT NULL,
  teacher_id  BIGINT,
  FOREIGN KEY (teacher_id) REFERENCES teachers(teacher_id) );
INSERT INTO courses VALUES (1,'国語',101);
INSERT INTO courses VALUES (2,'算数',102);
INSERT INTO courses VALUES (3,'理科',103);

-- 受講
DROP TABLE IF EXISTS student_courses;
CREATE TABLE student_courses (
  course_id  VARCHAR(16),
  student_id BIGINT,
  PRIMARY KEY (course_id, student_id),
  FOREIGN KEY (course_id)  REFERENCES courses(course_id),
  FOREIGN KEY (student_id) REFERENCES students(student_id));

INSERT INTO student_courses VALUES (1,301);
INSERT INTO student_courses VALUES (1,302);
INSERT INTO student_courses VALUES (1,303);
INSERT INTO student_courses VALUES (1,306);
INSERT INTO student_courses VALUES (1,307);
INSERT INTO student_courses VALUES (1,308);
INSERT INTO student_courses VALUES (1,310);
INSERT INTO student_courses VALUES (2,301);
INSERT INTO student_courses VALUES (2,309);
INSERT INTO student_courses VALUES (3,310);

create database

$ /usr/bin/sqlite3 test.sqlite3 < test_ddl.sql

test sql.js

<meta charset="utf8" />
<html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.2/sql-wasm.js">
</script>
<script>
  async function init_sqljs() {
      const sqlPromise = initSqlJs({
          locateFile:file=>`https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.2/${file}`
      });
      
      const dataPromise = fetch("test.sqlite3").then(res => res.arrayBuffer());
      const [SQL, buf] = await Promise.all([sqlPromise, dataPromise])
      const db = new SQL.Database(new Uint8Array(buf));

      let sql = `
SELECT c.course_name, t.teacher_name, s.student_name
FROM student_courses sc
JOIN students s ON(sc.student_id=s.student_id)
JOIN courses  c ON(sc.course_id=c.course_id)
JOIN teachers t ON(c.teacher_id=t.teacher_id)
WHERE s.student_name=?
ORDER BY c.course_id, s.student_id`;
      const stmt = db.prepare(sql);
      stmt.bind(["生徒一子"]);
      //console.log( stmt );
      
      let sql_result = "";
      while( stmt.step() ) {
          let row = stmt.getAsObject();
          sql_result += JSON.stringify(row);
      }
      document.querySelector("#sql_result").innerHTML = sql_result;
      
      stmt.free();
      //const dbBinary = db.export();
      db.close();
  }
  
  init_sqljs();
</script>
<body>
  https://sql.js.org
  https://github.com/sql-js/sql.js
  Output is here.
  <div id="sql_result"></div>d
</body>
</html>

sybase dbにある各テーブルの行数やファイルサイズの表示

mysqlのinformation_schema.tablesによるテーブルサイズの表示 - 改 - end0tknr's kipple - web写経開発

以前の上記entryにある通り、mysqlでは information_schema.tables に対しての select sqlで取得できますが、 sybase db の場合

select
     convert(varchar(30),o.name)  AS table_name
    ,row_count(db_id(), o.id)     AS row_count
    ,data_pages(db_id(), o.id, 0) * (@@maxpagesize/1024) AS size_kb
from sysobjects o
where type = 'U'
order by table_name

go

または isqlで接続し、以下

sp_spaceused <table>

go

認知的焦点化理論 - 利己的な人は長い目で見ると損

先程のentryにある「ダニングクルーガー効果」に関連し 「認知的焦点化理論」の存在を思い出したので、メモ

例えば、以下のurlが分かりやすい

利己的な人は長い目で見ると損をする!? 認知的焦点化理論など、運に関する3つの研究を紹介! | データで越境者に寄り添うメディア データのじかん

Highcharts の オレオレ テンプレート

久しぶりに www.highcharts.com を触ったら、随分と忘れていたので、メモ

https://www.highcharts.com/docs/index

↓こう書くと↑こう表示されます

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
  <a href="https://www.highcharts.com/docs/index">Highcharts documents</a>
  <!-- high chartのrendering先 -->
  <div id="chart_container" style="width:800px; height:400px;"></div>
  
  <script src="https://code.highcharts.com/highcharts.js"></script>
  <script src="my_highcharts.js"></script>
  <script>
    let my_charts = new MyHighCharts();
    my_charts.init_chart("chart_container");
  </script>
</body>
</html>
'use strict';

let chart_tmpl = {
    chart   :{renderTo: 'html_id', // 表示先となるhtml element id
              zoomType: 'xy',
              defaultSeriesType:'column'},
    title   :{text: 'end0tknrのHighchartsテスト',
              floating:true,
              style:{fontWeight:"medium",fontSize:"small"}},
    subtitle:{text: '' },
    xAxis: {categories :[], // X軸(横軸)の各値
            startOnTick:false, endOnTick:false},
    yAxis: [ // Y軸(縦軸)は、複数表示可能
        {title :{text:'温度', style:{color:'#89A54E'}},
         labels:{formatter:()=>{return this.value+'℃'},style:{color:'#89A54E'}},
         opposite: true  //trueの場合,グラフ右側に表示
        },
        {title :{text:'降水量', style:{color:'#4572A7'}},
         labels:{formatter:()=>{return this.value +'mm'},style:{color:'#4572A7'}},
         gridLineWidth: 0},
        {title :{text:'気圧', style:{color:'#AA4643'}},
         labels:{formatter:()=>{return this.value +'mb'},style:{color:'#AA4643'}},
         gridLineWidth: 0,
         opposite: true}
    ],
    series:[
        {name:'降水1',color:'#4572A7',type:'column',yAxis:1,stack:'grp1',data:[]},
        {name:'降水2',color:'#BAD1E6',type:'column',yAxis:1,stack:'grp1',data:[]},
        {name:'降水3',color:'#F5F5F5',type:'column',yAxis:1,stack:'grp2',data:[]},
        {name:'気温', color:'#89A54E',type:'spline',/*spline=曲線*/      data:[]},
        {name:'気圧', color:'#AA4643',type:'',/*折れ線*/ yAxis:2,        data:[],
         marker:{enabled: false},     dashStyle:'shortdot'} ],
    tooltip: {formatter:()=>{var unit = {'降水量1': 'mm',
                                         '降水量2': 'mm',
                                         '降水量3': 'mm',
                                         '気温': '°C',
                                         '気圧': 'mb'}[this.series.name];
                             return ''+ this.x +': '+ this.y +' '+ unit; } },
    plotOptions:{ column: { stacking: 'normal' } },
    legend: {layout:'vertical', verticalAlign:'top',align:'left',
             x:120, y:80,       floating:true,      backgroundColor:'#FFF'},
    accessibility:{enabled:false}, //実行時に何やらwarningが表示される為
    credits      :{enabled:false}, //グラフ領域のhigh chartsクレジット非表示
};

class MyHighCharts {
    constructor() {}

    init_chart=(render_html_elm_id)=>{
        // グラフtemplateのdeep copy
        let chart_src =
            Object.assign({},JSON.parse(JSON.stringify(chart_tmpl)));
        // rendering先となるhtml element idの設定
        chart_src.chart.renderTo   = render_html_elm_id;
        // X軸の値
        chart_src.xAxis.categories = ['Jan','Feb','Mar','Apr','May','Jun',
                                      'Jul','Aug','Sep','Oct','Nov','Dec'];
        // X軸の値
        chart_src.series[0].data=
            [49.9,71.5,106.4,129.2,144.0,176.0,135.6,148.5,216.4,194.1,95.6,54.4];
        chart_src.series[1].data=
            [19.9,41.5,76.4,99.2,114.0,146.0,105.6,118.5,186.4,164.1,65.6,24.4];
        chart_src.series[2].data=
            [39.9,61.5,96.4,119.2,134.0,166.0,125.6,138.5,206.4,184.1,85.6,44.4];
        chart_src.series[3].data=
            [7.0,6.9,9.5,14.5,18.2,21.5,25.2,26.5,23.3,18.3,13.9,9.6];
        chart_src.series[4].data=
            [1016,  1016,  1015.9,1015.5,1012.3,1009.5,
             1009.6,1010.2,1013.1,1016.9,1018.2,1016.7];
        // グラフの実体化
        let new_chart = new Highcharts.Chart( chart_src );
    }
}

Sybase (SAP)では WHERE IN句に複数条件はNG

sqlのwhere in って、複数条件(カラム)を指定できるんですね - end0tknr's kipple - web写経開発

上記entryにある通り、mysqlでは WHERE IN句に複数条件を指定できましたが Sybase (SAP)ではNGらしい

なので、SQLの実行速度は遅いでしょうが

SELECT pla.plan_numw, pla.addition_num, pla.revision
FROM plan_attr pla
WHERE (pla.plan_num+pla.addition_num)
   in ('XXXA5001201','XXXA5002101')
go

のように複数カラムを文字列連結し、 疑似的?に複数条件を指定できるようにしてみます