我輩はブロガーではない。ネタもまだない

SASとかDelphiあたりの人様の役に立たないネタを提供します

CDATA SAS.dsを使ってみる(その2:属性編)

CDATA SAS.dsを使ってみる(その1:データセットアクセス編)

に続き、CDATA SAS dataset Firedac componentの検証記事です
(いずれも検証時点で入手可能なβ版 21.0.7829 を使用しています)

今回はSASデータセットディスクリプタ部、属性について調べました。


属性は完璧には取得できない

検証に使用したデータセットです

data temp.fmt;
length char $10;
format 
time time8.
yymmdd yymmdd10.
e8601dt e8601dt19.
date date9.
weekdate weekdate21.
nengo nengo9.
jnengo jnengo16.
jdateymd jdateymd14.
datetime datetime16.
yen yen8.
dollar dollar12.2
comma comma7.
z z7.
hex hex6.
best12 best12.
best32 best32.
;
  array n{*} _numeric_;
  do i=1 to dim(n);
    n{i}=10000;
  end;
  char='SAMPLE';
  best12=1234567890.1234567;
  best32=1234567890.1234567;
  drop i;
run;
f:id:japelin:20210615111004p:plain
SASでの実行結果

さて、属性はTFDMetaInfoQueryを使い、以下のように取得します

var
 cnt:integer;
begin
  FDMetaInfoQuery1.Close;
  FDMetaInfoQuery1.Connection := FDConnection1;
  FDMetaInfoQuery1.MetaInfoKind := mkTableFields;
  FDMetaInfoQuery1.ObjectName   := Combobox1.Items[Combobox1.ItemIndex];
  FDMetaInfoQuery1.Open;
  cnt:=0;

  StringGrid1.RowCount:=FDMetaInfoQuery1.RecordCount;
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.Columns[0].Header := 'Name';
  StringGrid1.Columns[1].Header := 'Length';
  StringGrid1.Columns[2].Header := 'Precision';
  StringGrid1.Columns[3].Header := 'DataType.';
  StringGrid1.Columns[4].Header := 'TypeName';

  while(not(FDMetaInfoQuery1.Eof))do begin
    StringGrid1.Cells[0,cnt]:= FDMetaInfoQuery1.FieldByName('COLUMN_NAME').AsString;
    StringGrid1.Cells[1,cnt]:= FDMetaInfoQuery1.FieldByName('COLUMN_LENGTH').AsString;
    StringGrid1.Cells[2,cnt]:= FDMetaInfoQuery1.FieldByName('COLUMN_PRECISION').AsString;
    StringGrid1.Cells[3,cnt]:= FDMetaInfoQuery1.FieldByName('COLUMN_DATATYPE').AsString;
    StringGrid1.Cells[4,cnt]:= FDMetaInfoQuery1.FieldByName('COLUMN_TYPENAME').AsString;
    inc(cnt);
    FDMetaInfoQuery1.Next;
  end;
    FDMetaInfoQuery1.Close;

さて、結果は以下の通りです。

f:id:japelin:20210615111942p:plain
一部はフォーマットが認識されていない

実データはどうなってるでしょう。

char     / SAMPLE
time     / 2:46:40
yymmdd   / 1987/05/19
e8601dt  / 1960/01/01 2:46:40
date     / 1987/05/19
weekdate / 1987/05/19
nengo    / 10000
jnengo   / 10000
jdateymd / 10000
datetime / 1960/01/01 2:46:40
yen      / 10000
dollar   / 10000
comma    / 10000
z        / 10000
hex      / 10000
best12   / 1234567890.12346
best32   / 1234567890.12346

SASと同じ結果で認識できているのはNumeric型では

  • time8.
  • yymmdd10.

だけでした。

他の結果については

  • e8601dtは日付と時刻の間の「T」がない
  • date、weekdate、datetimeは日付値、日時値として認識されているが、正しいフォーマットではない
  • 日時以外の数値フォーマットについては軒並み生データのまま。
  • 16桁を超える数値については、最終桁が丸められている

また、属性については

  • Characterの場合は、lengthはそのまま取得できる。
  • フォーマットが適用された日付の場合は型が「datetime / date / time」となり、lengthもprecisionも0となる。値自体はロケールに依存しそうな気配(未確認)
  • Numericの場合は、lengthは0になり、precision(精度)が15(桁)のdouble型となる。


SQLにはSASのような「ラベル」「フォーマット」という概念がありませんので、そもそもラベルもフォーマットもその属性を取得することはできませんでした。
(なので、データ構造が公開されているXPTではバイナリから取得していました)
また、SASを起動しているわけではないのでDictionaryテーブルから情報を取得することもできません。

したがって、メタデータが必要であれば当該データセット以外に情報を保持しておく必要がありそうです。

なお、インデックスについては

  FDMetaInfoQuery1.MetaInfoKind := mkIndexes;

で取得できるはずなのですが、SASのインデックスは取得できませんでした。