Tips

テーブル名とフィールド名からフィールドのポインターを得る

日付2019/07/04
ID19-008
バージョン11以降
プラットフォームWin, Mac

以前、変数名などの名前からポインターを得る方法について記事を紹介したことがありました。

Tips: 変数、フィールドいずれでもポインターを取得出来るメソッド

変数の場合には、Get pointerで簡単にポインターを得ることができますが、テーブル名やフィールド名の場合、名前からポインターを得るのに少々回りくどい方法になりました。 4D v11以降では、システムテーブルにアクセスをすると、テーブル番号やフィールド番号を得ることができますので、得た番号からポインターを得ることが可能です。

それを踏まえて、例題を作成してみました。

  //名前からポインターを得る

C_TEXT($1)  // 変数名、テーブル名&フィールド名
C_POINTER($0)  // ポインター

C_POINTER($p)
C_LONGINT($pos;$len)
C_TEXT($name_table;$name_field)

Case of 
	: (Match regex("^\\[.+?\\]$";$1;1;$pos;$len))
		
		  //テーブル名のときは、テーブルのポインターを得る
		
		$name_table:=Substring($1;2;$len-2)
		
		ARRAY LONGINT($id_table;0)  // テーブル番号の一時的な格納場所
		Begin SQL
			SELECT TABLE_ID
			FROM _USER_TABLES
			WHERE TABLE_NAME = :$name_table
			INTO :$id_table ;
		End SQL
		
		If (Size of array($id_table)=1)
			$p:=Table($id_table{1})
		End if 
		
	: (Match regex("^\\[.+?\\]";$1;1;$pos;$len))
		
		  //テーブル名&フィールド名のときは、フィールドのポインターを得る
		
		$name_table:=Substring($1;2;$len-2)
		$name_field:=Substring($1;$pos+$len)
		
		ARRAY LONGINT($id_table;0)  // テーブル番号の一時的な格納場所
		ARRAY LONGINT($id_field;0)  // フィールド番号の一時的な格納場所
		Begin SQL
			SELECT TABLE_ID,COLUMN_ID
			FROM _USER_COLUMNS
			WHERE TABLE_NAME = :$name_table AND COLUMN_NAME = :$name_field
			INTO :$id_table,:$id_field ;
		End SQL
		
		If (Size of array($id_table)=1)
			$p:=Field($id_table{1};$id_field{1})
		End if 
		
	Else 
		
		  //変数名のときは単純なラッパー
		
		$p:=Get pointer($1)
		
End case 

// 得られたポインターを返す
$0:=$p

この例題は、SQLを利用してシステムテーブルにアクセスしていますが、SQLはパフォーマンスがあまり良くないので、ループ中で使う際には注意が必要になります。 パフォーマンスを重視するのであれば、得られたポインターを一時的にプロセス変数の配列などにキャッシュするようなどして、再利用するなどの工夫が必要です。

追加情報

4D v17でオブジェクト記法を利用してORDAを使うと、ポインター不要で、直接フィールドの値にアクセスできるようになります。

// ORDAの例題

$name_table:="テーブル名"
$name_field:="フィールド名"
$i:=0 //レコード位置(0始まり)

$selection:=ds[$name_table].all()
$value:=$selection[$i][$name_field] // $i番目のレコードの指定したフィールドの値を$valueに代入