色空間メソッドと色のアニメーションを拡張するjQueryプラグイン jQuery.iColor をバージョンアップしました。
選択範囲のテキストを操作するjQueryプラグインjQuery.selection
以下の内容は、古い内容です。
新しい記事で情報を確認してください。
http://blog.madapaja.net/entry/2012/05/09/070500
選択範囲のテキストを操作するためのjQueryプラグイン jQuery.selection を書いたので、アップしました。
IE6やFireFox3.5、Google Chrome 6など主要なブラウザでチェック済みです。
ファイルはこちら
http://jquery-selection.googlecode.com/svn/tags/(URLが間違っていたため訂正しました)
http://code.google.com/p/jquery-selection/downloads/list (圧縮ファイル)
簡単な説明
- bold;">$.getSelection([mode = 'text']):HTMLドキュメント内の選択されたテキスト/HTMLを取得する
- bold;">getSelection():テキストボックス/エリアの選択されたテキストを取得する
- bold;">replaceSelection(text[, caret = 'keep']):テキストボックス/エリアの選択されたテキストを置換する
- bold;">insertBeforeSelection(text[, caret = 'keep']):テキストボックス/エリアの選択されたテキストの前に文字列を挿入する
- bold;">insertAfterSelection(text[, caret = 'keep']):テキストボックス/エリアの選択されたテキストの後に文字列を挿入する
- bold;">getCaretPos():テキストボックス/エリアの選択範囲を取得する
- bold;">setCaretPos(range):テキストボックス/エリアの選択範囲を設定する
デモも併せてご確認ください。
$.getSelection([mode = 'text'])
HTMLドキュメント内の選択されたテキスト/HTMLを取得する
mode
modeには、'text'もしくは'html'を指定します。
指定しなかった場合は、'text'となります。
返り値
String型で mode に指定した値によって、選択されたテキストか、HTMLテキストが返ります。
getSelection()
テキストボックス/エリアの選択されたテキストを取得する
返り値
String型で選択されたテキストが返ります。
replaceSelection(text[, caret = 'keep'])
テキストボックス/エリアの選択されたテキストを置換する
text
置換後の文字列を指定します。
caret
caretには'keep'か'start'、'end'のいずれかを指定します。
指定しなかった場合は、'keep'となります。
- bold;">keep:選択範囲を保持します。(指定したtextが選択状態となります)
- bold;">start:キャレットを選択範囲の最初に移動します
- bold;">end:キャレットを選択範囲の後ろに移動します
insertBeforeSelection(text[, caret = 'keep'])
テキストボックス/エリアの選択されたテキストの前に文字列を挿入する
text
挿入する文字列を指定します。
caret
caretには'keep'か'start'、'end'のいずれかを指定します。
指定しなかった場合は、'keep'となります。
- bold;">keep:選択範囲を保持します。
- bold;">start:キャレットを選択範囲の最初に移動します
- bold;">end:キャレットを選択範囲の後ろに移動します
insertAfterSelection(text[, caret = 'keep'])
テキストボックス/エリアの選択されたテキストの後に文字列を挿入する
text
挿入する文字列を指定します。
caret
caretには'keep'か'start'、'end'のいずれかを指定します。
指定しなかった場合は、'keep'となります。
- bold;">keep:選択範囲を保持します。
- bold;">start:キャレットを選択範囲の最初に移動します
- bold;">end:キャレットを選択範囲の後ろに移動します
getCaretPos()
テキストボックス/エリアの選択範囲を取得する
返り値
Object型 {start: 選択開始位置, end: 選択終了位置} で選択範囲が返ります。
例
var pos = $('textarea').getCaretPos(); alert(''+ pos.start + ' から ' + pos.end + 'までが選択されています。');
setCaretPos(range)
テキストボックス/エリアの選択範囲を設定する
range
Object型 {start: 選択開始位置, end: 選択終了位置} で選択範囲を指定します。
例
var strLen = $('textarea').val().length; // 文字数を取得 // 全て選択します $('textarea').setCaretPos({ start: 0, // 最初から end : strLen // 最後まで });
ファイルはこちら
http://jquery-selection.googlecode.com/svn/tags/(URLが間違っていたため訂正しました)
http://code.google.com/p/jquery-selection/downloads/list (圧縮ファイル)
色空間メソッドと色のアニメーションを拡張するjQueryプラグインiColorを書いた
[色空間] - 今日も適当ダイアリーなどで、色空間の変換についての記事を書きましたが、それらを簡単に使えるように、jQueryプラグインとして書き直しました。
まだ、アルファ版なのですが、取り急ぎ公開しておきます。
ファイルはこちら
http://jquery-icolor.googlecode.com/svn/tags/
http://code.google.com/p/jquery-icolor/downloads/list (圧縮ファイル)
http://www.weekendphp.com/jQuery/jquery.color.js
http://www.weekendphp.com/jQuery/jquery.color-min.js
簡単な説明
このプラグインでは、jQueyrに下記3つが拡張されます。
- animateの拡張(色のアニメーションが行えます)
- getColorメソッドの追加(iColorオブジェクトを返します)
- iColorオブジェクト($.iColor)の追加
animateを拡張
jQuery単体ではanimateにて色のアニメーションが行えないのですが、行えるように拡張を行いました。
また、柔軟な指定に対応しました。
対応したプロパティ名は下記の通りです。
- color
- backgroundColor
- borderTopColor
- borderRightColor
- borderBottomColor
- borderLeftColor
- outlineColor
値は下記2通りの方法で指定出来ます。
サンプルを見た方がわかりやすいと思います。
$("#test1").animate({ backgroundColor: 'yellow' }, 2000); $("#test2").animate({ backgroundColor: // オブジェクトとして、一部の値を渡すことも出来ます。 { 'h': '+=1080', 's': '-=0.3', 'mode': 'HSV' } }, 3000); $("#test3").animate({ backgroundColor: 'rgba(255,255,0,0)', borderTopColor: 'lightblue', borderBottomColor: 'lightblue', borderLeftColor: 'lightblue', borderRightColor: 'lightblue' }, 2000); $("#test4").animate({ backgroundColor: { 'r': '-=100', 'b': 200, 'a': '+=0.5', 'mode': 'RGB' } }, 2000);
getColorメソッドの追加
iColor function getColor(attr)
attr にはCSSプロパティ名を指定します。
返り値はiColorオブジェクトとなります。
// iColor オブジェクトが返ります。 color = $('div#test1').getColor('background-color'); // こんな使い方もできます $('#getColorTest2').text( $('div#test1').getColor('background-color') // div#test1の背景色を取得 .change('h', '+=30') // hue (色相) を +30度 変える .getStr() // 色表現文字列を取得 );
iColorオブジェクトの追加
iColorオブジェクトは下記のいずれかにより生成されます。
// A) getColorメソッド color = $('div#test1').getColor('background-color'); // B) iColorコンストラクタ // B-1. 引数指定 color = jQuery.iColor(color1, color2, color3, [type = 'RGB']); color = jQuery.iColor(color1 color2, color3, [alpha], [type = 'RGBA']); // color1〜3は数値ですが、typeにより取り得る範囲が異なります。 // R, G, B: 0 〜 255 または 0% 〜 100% // H: 0〜360 (角度なので 0 と 360 は同値) // S, V, L: 0 〜 1 または 0% 〜 100% // alpha 値は 0〜1の数値です。 // type は色空間を表し次のいずれかを取ります。 // 'RGB', 'RGBA', 'HSV', 'HSVA', 'HLS', 'HLSA', 'HSL', 'HSLA' // B-2. 配列指定 color = jQuery.iColor(colorArray, [type = 'RGB'||'RGBA']); // colorArray は [color1, color2, color3] // または [color1, color2, color3, alpha] となります。 // B-3. オブジェクト指定 color = jQuery.iColor(colorArray, [type = 'RGB'||'RGBA']); // 例: jQuery.iColor({r: 255, g: 255, b: 255}, 'RGB'); // jQuery.iColor({r: 255, g: 255, b: 255, type: 'RGB'}); // B-4. CSS色表現指定 color = jQuery.iColor(colorStr); // colorStr は、 blue や #rrggbb、rgb(255,255,0)、hsla(300,10%,50%,1) など
iColorオブジェクトのプロパティ
iColorオブジェクトは下記のプロパティを持ちます。
色要素プロパティ
typeプロパティに応じて、それぞれの色要素プロパティを持ちます。
たとえば、typeがRGBだった場合、r、g、bという3つの色要素プロパティを持つことになります。
iColorオブジェクトのメソッド
iColorオブジェクトは下記のメソッドを持ちます。
iColor function to(type)
iColor function toRGB()
iColor function toRGBA()
iColor function toHSV()
iColor function toHSVA()
iColor function toHSL()
iColor function toHSLA()
iColor function toHLS()
iColor function toHLSA()
iColorオブジェクトの色空間変換し、新しいiColorオブジェクトを返します。
toXXX 形式は、to('XXX')のショートカットであり、同一の挙動をします。
iColor function change(target, val, mode)
iColorオブジェクトの特定の色要素を変更し、新しいiColorオブジェクトを返します。
target には変更したい色要素名(1文字の文字列)を指定します。
val には、変更したい値(1 や '255' など)、もしくは変化させたい量('+=0.1' や '-=30' など)を指定出来ます。
詳細はデモで確認してください。
RGB色空間とHLS(HSL, HSI)色空間の相互変換 Javascript版
RGB色空間とHSV色空間の相互変換 Javascript版 - 今日も適当ダイアリー で Javascript での RGB と HSV の相互変換処理を書いたので、今度はRGB と HLS(HSL、HSIと呼ばれる事もある)の相互変換をメモ。
HLS色空間については HLS色空間 - Wikipedia などを参照してください。
RGB から HLS色空間へのコンバート
/** * RGB を HLS へ変換します * * @param {Number} r red値 ※ 0〜255 の数値 * @param {Number} g green値 ※ 0〜255 の数値 * @param {Number} b blue値 ※ 0〜255 の数値 * @return {Object} {h, l, s} ※ h は 0〜360の数値、l/s は 0〜1 の数値 */ function RGBtoHLS(r, g, b) { var h, // 0..360 l, s; // 0..1 // 0..1 に変換 r = r / 255; g = g / 255; b = b / 255; var max = Math.max(Math.max(r, g), b), min = Math.min(Math.min(r, g), b); // hue の計算 if (max == min) { h = 0; // 本来は定義されないが、仮に0を代入 } else if (max == r) { h = 60 * (g - b) / (max - min) + 0; } else if (max == g) { h = (60 * (b - r) / (max - min)) + 120; } else { h = (60 * (r - g) / (max - min)) + 240; } while (h < 0) { h += 360; } // Lightness の計算 l = (max + min) / 2; // Saturation の計算 if (max == min) { s = 0; } else { s = (l < 0.5) ? (max - min) / (max + min) : (max - min) / (2.0 - max - min); } return {'h': h, 'l': l, 's': s, 'type': 'HLS'}; }
HLS から RGB色空間へのコンバート
/** * HLS を RGB へ変換します * * @param {Number} h hue値 ※ 0〜360の数値 * @param {Number} l lightness値 ※ 0〜1 の数値 * @param {Number} s saturation値 ※ 0〜1 の数値 * @return {Object} {r, g, b} ※ r/g/b は 0〜255 の数値 */ function HLStoRGB(h, l, s) { var r, g, b; // 0..255 while (h < 0) { h += 360; } h = h % 360; // 特別な場合 saturation = 0 if (s == 0) { // → RGB は V に等しい l = Math.round(l * 255); return {'r': l, 'g': l, 'b': l, 'type': 'RGB'}; } var m2 = (l < 0.5) ? l * (1 + s) : l + s - l * s, m1 = l * 2 - m2, tmp; tmp = h + 120; if (tmp > 360) { tmp = tmp - 360 } if (tmp < 60) { r = (m1 + (m2 - m1) * tmp / 60); } else if (tmp < 180) { r = m2; } else if (tmp < 240) { r = m1 + (m2 - m1) * (240 - tmp) / 60; } else { r = m1; } tmp = h; if (tmp < 60) { g = m1 + (m2 - m1) * tmp / 60; } else if (tmp < 180) { g = m2; } else if (tmp < 240) { g = m1 + (m2 - m1) * (240 - tmp) / 60; } else { g = m1; } tmp = h - 120; if (tmp < 0) { tmp = tmp + 360 } if (tmp < 60) { b = m1 + (m2 - m1) * tmp / 60; } else if (tmp < 180) { b = m2; } else if (tmp < 240) { b = m1 + (m2 - m1) * (240 - tmp) / 60; } else { b = m1; } return {'r': Math.round(r * 255), 'g': Math.round(g * 255), 'b': Math.round(b * 255), 'type': 'RGB'}; }
RGB色空間とHSV色空間の相互変換 Javascript版
RGB色空間とHSV色空間の相互変換 PHP版 - 今日も適当ダイアリー の記事に、「Javascript RGB HSV変換」というキーワード検索で入ってくる方がいらっしゃるようなので、Javascript版も一応掲載しておきます。
HSV色空間については HSV色空間 - Wikipedia を参照してください。
上記Wikipediaに載っている変換式をそのままjavascriptにしただけなので、特に難しい事はしていません。
jQueryのプラグインにすれば、ちょっとした時に使えるかも?と思いましたが、意外に面倒そうなので、書いたらあらためて、このブログで紹介したいと思います。
RGB から HSV色空間へのコンバート
/** * RGB配列 を HSV配列 へ変換します * * @param {Number} r red値 ※ 0〜255 の数値 * @param {Number} g green値 ※ 0〜255 の数値 * @param {Number} b blue値 ※ 0〜255 の数値 * @param {Boolean} coneModel 円錐モデルにするか * @return {Object} {h, s, v} ※ h は 0〜360の数値、s/v は 0〜255 の数値 */ function RGBtoHSV (r, g, b, coneModel) { var h, // 0..360 s, v, // 0..255 max = Math.max(Math.max(r, g), b), min = Math.min(Math.min(r, g), b); // hue の計算 if (max == min) { h = 0; // 本来は定義されないが、仮に0を代入 } else if (max == r) { h = 60 * (g - b) / (max - min) + 0; } else if (max == g) { h = (60 * (b - r) / (max - min)) + 120; } else { h = (60 * (r - g) / (max - min)) + 240; } while (h < 0) { h += 360; } // saturation の計算 if (coneModel) { // 円錐モデルの場合 s = max - min; } else { s = (max == 0) ? 0 // 本来は定義されないが、仮に0を代入 : (max - min) / max * 255; } // value の計算 v = max; return {'h': h, 's': s, 'v': v}; }
HSV から RGB色空間へのコンバート
/** * HSV配列 を RGB配列 へ変換します * * @param {Number} h hue値 ※ 0〜360の数値 * @param {Number} s saturation値 ※ 0〜255 の数値 * @param {Number} v value値 ※ 0〜255 の数値 * @return {Object} {r, g, b} ※ r/g/b は 0〜255 の数値 */ function HSVtoRGB (h, s, v) { var r, g, b; // 0..255 while (h < 0) { h += 360; } h = h % 360; // 特別な場合 saturation = 0 if (s == 0) { // → RGB は V に等しい v = Math.round(v); return {'r': v, 'g': v, 'b': v}; } s = s / 255; var i = Math.floor(h / 60) % 6, f = (h / 60) - i, p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s) switch (i) { case 0 : r = v; g = t; b = p; break; case 1 : r = q; g = v; b = p; break; case 2 : r = p; g = v; b = t; break; case 3 : r = p; g = q; b = v; break; case 4 : r = t; g = p; b = v; break; case 5 : r = v; g = p; b = q; break; } return {'r': Math.round(r), 'g': Math.round(g), 'b': Math.round(b)}; }
SlicehostからさくらのVPSへ乗り換えようか
趣味利用のサーバーとして、Rackspace Managed Cloud Services—More than just infrastructureを使っているんだけど、VPS(仮想専用サーバ)|さくらインターネット - 無料お試し実施中に乗り換えようか考えている。
とりあえず、昨日、申し込みをして、さくらのVPSをお試し中。
基本的なスペック(価格も含めて)は、さくらのVPSが上回っているんだけど、ちょっと僕が迷っているのは下記の3点だ。
Slicehostで出来て、さくらのVPSで出来ないこと
(自分が迷っている点のみ)
- IPアドレス追加がない(1個だけ)
- もう1つ(計2つ)欲しいんだよね。。
Slicehostの場合は、追加IPは1個につき $2.0で出来る。 - ネームサーバがついてこない
- 自分で動かすのはいやだし。さくらのDNSサーバーでできるのかな?(でも、月額がVPSより高い。。。)
Slicehostなら標準でついてくる。 - IPアドレスの逆引きができない
- Slicehostなら標準でできる。
オプション対応とかでもいいので、してくれたら、はい変えます!って感じなのだけれど。
もうちょっと悩もうと思う。
結局、さくらに移転することになる気もするけど。
パスワード(ランダム)文字列を生成してみる
パスワード自動生成のための javascript を書いてみた。
要件
要件は、下記の通りとします。
- 生成する文字列の文字数を指定できること
- 生成する文字列に使用する文字リストを指定できること
- 生成する文字列の文字が重複しないようにするか否かを指定できること
関数定義
関数の定義は以下の通り
パスワード文字列(ランダム文字列)を生成する @param {Number} i 生成する文字列の文字数 @param {String} s 生成する文字列に使用する文字リスト @param {Boolean} f 文字が重複しないようにするか否か @returns {String} 生成された文字列
素直にforループでまわしてみる
単純に、forループを使ってランダムな文字列を生成してみます。
なお、今回は、一回限り使えればよかったので無名関数で定義してます。(なので、使いきりです)
(function(i,s,f) { var p = ''; for (; i > 0; i--) { // 文字リストからランダムに選択 var j = Math.floor(Math.random() * s.length); // 結果文字列に追加 p += s.charAt(j); // 文字を重複させない場合は今回使った文字をリストから削除 if (f) { s = s.substr(0, j) + s.substr(j + 1); } } return p; })( 10, // 文字数 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789', // 文字リスト true); // 文字を重複させない場合はtrue
念のため言っておくと、実際に利用するには、下記のように記述します。
document.getElementById('ターゲットのID').value = /* ここに本体のコード */
やっている事は単純で、forループ内で文字リストからランダムな一文字を選択して、それを結果文字列に追加しているだけです。
文字を重複させない場合は、文字リストから今使った文字を削除していく感じですね。
実行例:http://www.weekendphp.com/misc/blog/hatena/ja9/2010-09-01.1.html
圧縮してみる
上記のコードをあーだこーだして、改行やスペースなどを取っ払って、圧縮(?)してみます。
(function(i,s,f){for(var m=Math,p='';i>0;i--){var j=m.floor(m.random()*s.length);p+=s.charAt(j);s=f?s.substr(0,j)+s.substr(j+1):s}return p})(10,'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789',true);
本体部分は140バイトになりました。
もっと短く出来ないかと、別の方法も考えてみます。
こんどは再帰関数にしてみる
再帰関数にすれば、もっと短くなるのでは?と思い、チャレンジしてみます。
今回は、勉強がてら無名関数を再帰してみます。
自分自身は、arguments.calleeで参照できます。
参考:arguments.callee - JavaScript | MDN
(function(i,s,f) { var j = Math.floor(Math.random() * s.length); // 文字リストからランダムに選択 if (i <= 1) { return s.charAt(j); } // 文字を重複させない場合は今回使った文字をリストから削除 if (f) { s = s.substr(0, j) + s.substr(j + 1); } // i > 1 なら再帰させる return s.charAt(j) + arguments.callee(i - 1, s, f); // 自分自身を呼び出す })( 10, // 文字数 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789', // 文字リスト true); // 文字を重複させない場合はtrue
やっている事自体は、forの時と大差ありません。
圧縮してみる
あーだこーだします。
(function(i,s,f){var m=Math,j=m.floor(m.random()*s.length);return s.charAt(j)+(i>1?arguments.callee(i-1,f?s.substr(0,j)+s.substr(j+1):s,f):'')})(10,'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789',true);
どうかな?
と思ったら、本体部分は144バイトでした。
forループより4バイト増えてしまいました。
そもそも、arguments.callee という変数/メソッド名が長いので、不利だったぽいです。
また、時間が時間があったら別の方法も考えてみようかな。
RGB色空間とHSV色空間の相互変換 PHP版
PHP配列とCSS色表現の相互変換 - 今日も適当ダイアリー に続いて、 relColors に使った関数を公開します。
色の明度や色相を計算するために、いったんRGBで表現された色情報を、HSV色空間に変換した上で計算を行いました。
HSV色空間については HSV色空間 - Wikipedia を参照してください。
RGB から HSV色空間へのコンバート
変換式は、上記したWikipediaに載っているので、それを素直にPHPで書きました。
<?php /** * RGB配列 を HSV配列 へ変換します * * @param array $arr array(r, g, b) ※ r/g/b は 0〜255 の数値 * @param bool $coneModel 円錐モデルにするか * @return array array(h, s, v) ※h は 0〜360の数値、s/v は 0〜255 の数値 */ function RGBtoHSV($arr, $coneModel = false) { $h = 0; // 0..360 $s = 0; // 0..255 $v = 0; // 0..255 $max = max($arr); $min = min($arr); // hue の計算 if ($max == $min) { $h = 0; // 本来は定義されないが、仮に0を代入 } else if ($max == $arr[0]) { // MAX = R // 60 * (G-B)/(MAX-MIN) + 0 $h = 60 * ($arr[1] - $arr[2]) / ($max - $min) + 0; } else if ($max == $arr[1]) { // MAX = G // 60 * (B-R)/(MAX-MIN) + 120 $h = (60 * ($arr[2] - $arr[0]) / ($max - $min)) + 120; } else { // MAX = B // 60 * (R-G)/(MAX-MIN) + 240 $h = (60 * ($arr[0] - $arr[1]) / ($max - $min)) + 240; } while ($h < 0) { $h += 360; } // saturation の計算 if ($coneModel) { // 円錐モデルの場合 $s = $max - $min; } else { if ($max == 0) { // 本来は定義されないが、仮に0を代入 $s = 0; } else { $s = ($max - $min) / $max * 255; } } // value の計算 $v = $max; return array( $h, // H $s, // S $v, // V ); }
HSV から RGB色空間へのコンバート
<?php /** * HSV配列 を RGB配列 へ変換します * * @param array $arr array(h, s, v) ※h は 0〜360の数値、s/v は 0〜255 の数値 * @return array array(r, g, b) ※ r/g/b は 0〜255 の数値 */ function HSVtoRGB($arr) { $r = 0; // 0..255 $g = 0; // 0..255 $b = 0; // 0..255 while ($arr[0] < 0) { $arr[0] += 360; } $arr[0] = $arr[0] % 360; // 特別な場合 if ($arr[1] == 0) { // S = 0.0 // → RGB は V に等しい return array( round($arr[2]), round($arr[2]), round($arr[2]), ); } $arr[1] = $arr[1] / 255; // Hi = floor(H/60) mod 6 $i = floor($arr[0] / 60) % 6; // f = H/60 - Hi $f = ($arr[0] / 60) - $i; // p = V (1 - S) $p = $arr[2] * (1 - $arr[1]); // q = V (1 - fS) $q = $arr[2] * (1 - $f * $arr[1]); // t = V (1 - (1 - f) S) $t = $arr[2] * (1 - (1 - $f) * $arr[1]); switch ($i) { case 0 : // R = V, G = t, B = p $r = $arr[2]; $g = $t; $b = $p; break; case 1 : // R = q, G = V, B = p $r = $q; $g = $arr[2]; $b = $p; break; case 2 : // R = p, G = V, B = t $r = $p; $g = $arr[2]; $b = $t; break; case 3 : // R = p, G = q, B = V $r = $p; $g = $q; $b = $arr[2]; break; case 4 : // R = t, G = p, B = V $r = $t; $g = $p; $b = $arr[2]; break; case 5 : // R = V, G = p, B = q $r = $arr[2]; $g = $p; $b = $q; break; } return array( round($r), // r round($g), // g round($b), // b ); }
DB内のテーブル名一覧、テーブル情報などを取得するSQL
PHPで新人教育向けにSQL(ここでは PostgreSQL)勉強用プログラムを制作しているのだけど、その中で、DB内のテーブル名一覧や、テーブル情報、列情報などを表示させたい、と思った。
で、お題を追加や変更時になるべく最小限の変更で済むようにするには……とかそんな事を思ったら、やっぱりDBの事はDBに聞け、って結論に。
始めて pg_* 系のテーブルをあーだこーだして、たどり着いたSQLを(ツッコミどころがありそうで心配なのですが)備忘録代わりに記載しておきます。
テーブル一覧の取得
SELECT cls.oid, -- pg_class.oid nsp.nspname, -- テーブルを持つスキーマ名 public とか usr.usename, -- 所有ユーザー名 cls.relname -- テーブル名 FROM pg_class cls INNER JOIN pg_namespace nsp ON (cls.relnamespace = nsp.oid) INNER JOIN pg_user usr ON (cls.relowner = usr.usesysid) WHERE cls.relkind = 'r' -- AND nsp.nspname = 'public' -- スキーマ名で絞込み -- AND usr.usename = 'user1' -- 所有ユーザー名で絞込み ORDER BY nsp.nspname, usr.usename, cls.relname
pg_class を基点に、ネームスペースとユーザー情報を取得します。
relkind は種別を表していますが、小文字の r が通常のテーブル、となります。
シーケンス一覧の取得
SELECT cls.oid, -- pg_class.oid nsp.nspname, -- シーケンスを持つスキーマ名 public とか usr.usename, -- 所有ユーザー名 cls.relname -- テーブル名 FROM pg_class cls INNER JOIN pg_namespace nsp ON (cls.relnamespace = nsp.oid) INNER JOIN pg_user usr ON (cls.relowner = usr.usesysid) WHERE cls.relkind = 'S' -- nsp.nspname = 'public' -- スキーマ名で絞込み -- usr.usename = 'user1' -- 所有ユーザー名で絞込み ORDER BY nsp.nspname, usr.usename, cls.relname
やっている事は、テーブル一覧の取得と全く変わりません。
relkind が大文字の S がシーケンスを表します。
テーブル列一覧の取得
上記テーブル一覧取得の際にゲットした「pg_class.oid」を基に列の一覧を取得します。
SELECT colname as "列名", CASE WHEN size IS NULL THEN datatype -- サイズ情報が取得できた場合は付加 ELSE datatype || ' (' || size || ')' END AS "データ型", CASE -- NOT NULL情報 と DEFAULT情報をマージ WHEN "notnull" IS NOT NULL AND "default" IS NOT NULL THEN "notnull" || ' ' || "default" -- ELSE COALESCE("notnull", "default") END AS "属性" FROM ( SELECT attr.attnum AS idx, -- 列番号 attr.attname AS colname, -- 列名 CASE typ.typname -- 分かりやすい名前に変更 WHEN 'int2' THEN 'SMALLINT' WHEN 'int4' THEN 'INT' WHEN 'int8' THEN 'BIGINT' WHEN 'float4' THEN 'REAL' WHEN 'float8' THEN 'DOUBLE' WHEN 'bpchar' THEN 'CHAR' ELSE UPPER(typ.typname) END AS datatype, -- データ型 -- attr.atttypmod が正の整数なら、 -- サイズ付加情報あり? -- (よく調べて無いので自信なし) CASE WHEN attr.atttypmod > 0 THEN CASE typ.typname WHEN 'numeric' THEN (attr.atttypmod - 4) / 65536 WHEN 'decimal' THEN (attr.atttypmod - 4) / 65536 WHEN 'date' THEN COALESCE(attr.atttypmod - 4, 10) WHEN 'time' THEN COALESCE(attr.atttypmod - 4, 8) WHEN 'timestamp' THEN COALESCE(attr.atttypmod - 4, 19) ELSE attr.atttypmod - 4 END END AS size, -- attnotnull が true なら NOT NULL CASE attr.attnotnull WHEN TRUE THEN 'NOT NULL' ELSE NULL END AS notnull, -- atthasdef が true なら DEFAULT 値あり CASE attr.atthasdef WHEN TRUE THEN 'DEFAULT ' || adef.adsrc ELSE NULL END AS default FROM pg_class cls INNER JOIN pg_attribute attr ON (cls.oid = attr.attrelid) INNER JOIN pg_type typ ON (attr.atttypid = typ.oid) -- デフォルト値情報 LEFT OUTER JOIN pg_attrdef adef ON (cls.oid = adef.adrelid AND attr.attnum = adef.adnum) WHERE cls.oid = ? -- pg_class.oid を入れよ -- 列番号が0以下の場合、システム列なので対象にしない AND attr.attnum >= 0 -- attisdropped が TRUE なら、 -- この列はすでに削除されていて無効状態 AND attr.attisdropped IS NOT TRUE AND typ.typisdefined ) AS tbl ORDER BY idx;
メジャーどころの型でしか試してないし、複合型などの事は一切考えずに書いているので、問題があるかもしれません。
特にサイズ情報の取得は自信がない(=適当)です。
必要があったら、また調べて書き直したいと思います。
というか、コメントで教えていただけると助かります。(自堕落ですみません)
テーブルインデックスの取得
「pg_class.oid」を基にテーブルインデックス情報を取得します。
SELECT cls.relname AS name, -- インデックス名 ( CASE -- プライマリキー WHEN idx.indisprimary THEN 'PRIMARY KEY, ' -- ユニーク属性 WHEN idx.indisunique THEN 'UNIQUE, ' END || am.amname -- インデックスのアクセスメソッド名 || ' (' -- 列名の取得(カンマ区切りで並べる) || ARRAY_TO_STRING(ARRAY( SELECT attr.attname FROM pg_class cls2 INNER JOIN pg_attribute attr ON (cls2.oid = attr.attrelid) WHERE cls2.oid = idx.indrelid AND attr.attnum = ANY(idx.indkey) ), ', ') || ')' )AS value -- 情報 FROM pg_index idx INNER JOIN pg_class cls ON (idx.indexrelid = cls.oid) INNER JOIN pg_am am ON (cls.relam = am.oid) WHERE idx.indrelid = ? -- pg_class.oid を入れよ ORDER BY indexrelid;
テーブルチェック制約 / 外部キー制約の取得
「pg_class.oid」を基にチェック制約 / 外部キー制約を取得します。
SELECT con.conname AS name, -- 制約名 pg_get_constraintdef(con.oid) AS value -- 情報 FROM pg_constraint con WHERE con.conrelid = ? -- pg_class.oid を入れよ AND (con.contype = 'c' OR con.contype = 'f') ORDER BY con.contype, conname;
テーブルトリガの取得
「pg_class.oid」を基にテーブルトリガ名、実行する関数情報を取得します。
SELECT trg.tgname, -- トリガ名 prc.proname, -- 実行する関数名 rtrim(replace(encode(trg.tgargs, 'escape') , E'\\000', ', '),', ') -- 引数 FROM pg_trigger trg INNER JOIN pg_proc prc ON (trg.tgfoid = prc.oid) WHERE trg.tgrelid = 17812 -- pg_class.oid を入れよ AND trg.tgenabled AND trg.tgisconstraint IS FALSE
トリガが実行されるタイミングは取得していません。
(面倒そうだったので、機会があれば調べてみようと思います。)
間違い、過不足、他のいい方法などありましたら、コメントで教えてください。
よろしくお願いします。
PHP配列とCSS色表現の相互変換
前回(色をアルファブレンドする - 今日も適当ダイアリー)にて、 relColors に使った使い回せそうな関数の公開を始めたのですが、ユーティリティ関数を書くのをすっかり忘れていました。
ということで、色テキスト表現からPHP配列の相互変換の関数を提示しておきます。
たいした事してないですけどね。
PHPで16進数テキストを integer にしたい場合は hexdec を使うとか、integer から16進表現にする場合は sprintf を使うとか、そこあたりは、よく忘れますよね。
初めてこの関数を聞いたっていう方は、頭の片隅においておくと、何かの時に便利かもと思います。
<?php /** * 色表現テキスト(#rrggbb 形式) を配列形式に変換します * * @param string $str 色表現テキスト(#rrggbb 形式) * @return array array(r, g, b) */ function getColor($str) { // 先頭の # を除去 (#rrggbb → rrggbb) if (strpos($str, '#') === 0) { $str = substr($str, 1); } // 先頭の 0x を除去 (0xrrggbb → rrggbb) if (strpos($str, '0x') === 0) { $str = substr($str, 2); } // 6 桁にそろえる switch (strlen($str)) { case 6: // 6桁ならそのまま break; case 3: // 3桁なら6桁に (rgb → rrggbb) $str = $str[0] . $str[0] . $str[1] . $str[1] . $str[2] . $str[2]; break; default: // それ以外はNG return false; } $matches = array(); // rrggbb を色事にキャプチャ if (preg_match('/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i', $str, $matches) != 1) { // rrggbb (それぞれは0~9 か a〜f) 以外ならNG return false; } return array( hexdec('0x' . $matches[1]), // (int) r hexdec('0x' . $matches[2]), // (int) g hexdec('0x' . $matches[3]), // (int) b ); } /** * 配列形式 を 色表現テキスト(#rrggbb 形式) に変換します * * @param array $arr array(r, g, b) * @param bool $compress 短い色表現(#rgb 形式) を許すか * @param string $prefix プレフィックス (# 以外にしたい場合は指定) * @return string 色表現テキスト(#rrggbb 形式) */ function getText($arr, $compress = true, $prefix = '#') { // マイナス値が入っていたらNG if (min($arr) < 0) { return false; } // rrggbb 形式に変換 (integer 型に強制しておく) $tmp = sprintf('%02x%02x%02x', (int) $arr[0], (int) $arr[1], (int) $arr[2]); // 6桁にならない場合は失敗 (256以上が入っているとそうなる) if (strlen($tmp) !== 6) { return false; } // 短い色表現を許す場合で、 // rr/gg/bb のそれぞれの上位と下位が同一であれば if ($compress && $tmp[0] == $tmp[1] && $tmp[2] == $tmp[3] && $tmp[4] == $tmp[5]) { // 3桁(rgb)にする $tmp = $tmp[0] . $tmp[2] . $tmp[4]; } return $prefix . $tmp; }
こんなもんです。