记孟买的一个夜晚

今天孟买出大事了,颇有影响的某政党的一位首脑被捕,将被带到孟买接受审判。
党羽在多处砸车烧铺闹事,搞到人人自危。平时的孟买路上车暴多,
今晚明显少了,回家一路畅通无阻。
外面乱叫的乌鸦,昏暗的夜晚,幽闷的空气中弥漫着一股躁动的味道。。。

在VIM中搜索文件夹

现在主流的编辑器都有搜索文件夹的功能,VIM同样也能实现。

vimgrep是VIM寻找模式匹配的内部方法,可以自动识别换行符和编码,并且
可以使用VIM强大的正则表达式。缺点是相对慢些,因为所有文件都要读
入内存。

语法
:vim[grep][!] /{pattern}/[g][j] {file} …
            Search for {pattern} in the files {file} … and set
            the error list to the matches.
            Without the ‘g’ flag each line is added only once.
            With ‘g’ every match is added.

            {pattern} is a Vim search pattern.  Instead of
            enclosing it in / any non-ID character (see
            |’isident’|) can be used, so long as it does not
            appear in {pattern}.
            ‘ignorecase’ applies.  To overrule it put |/c| in the
            pattern to ignore case or |/C| to match case.
            ‘smartcase’ is not used.

            When a number is put before the command this is used
            as the maximum number of matches to find.  Use
            ":1vimgrep pattern file" to find only the first.
            Useful if you only want to check if there is a match
            and quit quickly when it’s found.

            Without the ‘j’ flag Vim jumps to the first match.
            With ‘j’ only the quickfix list is updated.
            With the [!] any changes in the current buffer are
            abandoned.

来个简单的例子
在 d:mydocs下查找含有“弹冠相庆”的txt文档,但不跳到第一个匹配
:vimgrep /弹冠相庆/gj d:/mydocs/*/*.txt
如果要包含子文件夹,则用

:vimgrep /弹冠相庆/gj d:/mydocs/**/*.txt
打开quickfix窗口查看匹配结果
:cw

参考资料:

http://vimcdoc.sourceforge.net/doc/quickfix.html

:h vimgrep

Oracle Virtual Private Database

Oracle VPD(虚拟专有数据库)是从Oracle 8i (8.1.5)引入的一个新特性,为数据库提供了行级别
的安全性 (Row Level Security)或者说细粒度存取控制 (Fine Grained Access Control).
VPD的主要思想就是将访问限定到表中特定的行,这样每个用户将看到完全不同的数据集,
只能对这些被授权的数据进行增删查改。
Oracle 10g中VPD又有进一步完善,使得select操作可以基于列级别的控制(Column-Level Privacy).

关键词: VPD, FGAC,  Row Level Security, Column-Level Privacy, dbms_rls, add_policy

下面是个简单例子 (翻译自http://www.adp-gmbh.ch/ora/security/vpd/index.html)。

在这个例子里,假设一个公司由不同的部门组成(每个部门有一条记录在department表)。一个员
工只能属于一个部门,一个部门可以有一些机密信息记录在department_secrets表。

create table department (
  dep_id int primary key,
  name    varchar2(30)
);

create table employee (
  dep_id references department,
  name    varchar2(30)
);

create table department_secrets (
  dep_id references department,
  secret varchar2(30)
);

插入一些机密信息:

insert into department values (1, ‘Research and Development’);
insert into department values (2, ‘Sales’                   );
insert into department values (3, ‘Human Resources’         );

insert into employee values (2, ‘Peter’);
insert into employee values (3, ‘Julia’);
insert into employee values (3, ‘Sandy’);
insert into employee values (1, ‘Frank’);
insert into employee values (2, ‘Eric’ );
insert into employee values (1, ‘Joel’ );

insert into department_secrets values (1, ‘R+D Secret #1’  );
insert into department_secrets values (1, ‘R+D Secret #2’  );
insert into department_secrets values (2, ‘Sales Secret #1’);
insert into department_secrets values (2, ‘Sales Secret #2’);
insert into department_secrets values (3, ‘HR Secret #1’   );
insert into department_secrets values (3, ‘HR Secret #2’   );

对于任何一个员工,只能看到本部门的机密信息,而不能看见别的部门的机密信息。
为了在Oracle中实现这个功能,我们需要创建一个包,一个触发器以及设置一个策略。
首先创建一个包。

create or replace package pck_vpd

as
  p_dep_id department.dep_id%type;

  procedure set_dep_id(v_dep_id department.dep_id%type);

  function predicate (obj_schema varchar2, obj_name varchar2) return varchar2;
end pck_vpd;
/

create or replace package body pck_vpd as
 
  procedure set_dep_id(v_dep_id department.dep_id%type) is
  begin
    p_dep_id := v_dep_id;
  end set_dep_id;

  function predicate (obj_schema varchar2, obj_name varchar2) return varchar2 is
  begin
    return ‘dep_id = ‘ || p_dep_id;
  end predicate;
 
end pck_vpd;
/

然后定义一个触发器,当用户登陆数据库时,这个触发器将被触发。它找到用户的部门id(dep_id)
并调用包里的set_dep_id存储过程。

create or replace trigger trg_vpd
  after logon on database
declare
  v_dep_id department.dep_id%type;
begin
  select dep_id into v_dep_id
  from employee where upper(name) = user;

  pck_vpd.set_dep_id(v_dep_id);
end;
/

最后,定义一条策略。这条策略表明了如果用户执行一条select语句(注:实际上不止是select,
取决于policy的定义,本例中是select, update, delete),哪个存储过程返回的结果会被用来添加
到where子句中 (注:本例中是’dep_id = ‘ || p_dep_id, 其中p_dept_id会用实际值代替)。

begin
dbms_rls.add_policy  (
  user,
  ‘department_secrets’,
  ‘choosable policy name’,
  user,
  ‘pck_vpd.predicate’,
  ‘select,update,delete’);
end;
/

为了测试上述设置,创建一些用户。

create user frank identified by frank default tablespace users temporary tablespace temp;
create user peter identified by peter default tablespace users temporary tablespace temp;
create user julia identified by julia default tablespace users temporary tablespace temp;

授予必要的权限。

grant all on department_secrets to frank;
grant all on department_secrets to peter;
grant all on department_secrets to julia;

grant create session to frank;
grant create session to peter;
grant create session to julia;

创建一个共有的别名。

create public synonym department_secrets for department_secrets;

Frank (属于R+D部门) 执行一条查询….

connect frank/frank;

select * from department_secrets;

    DEP_ID SECRET
———- ——————————
         1 R+D Secret #1
         1 R+D Secret #2

Peter (属于Sales部门) 执行一条查询….

connect peter/peter;

select * from department_secrets;

    DEP_ID SECRET
———- ——————————
         2 Sales Secret #1
         2 Sales Secret #2

delete, update的情况与select类似.

补充:如果要实现select时对Column-Level的控制,比如说,当查询中包含secret这个字段时所添加的
策略才生效,可以把上面的
begin
dbms_rls.add_policy  (
  user,
  ‘department_secrets’,
  ‘choosable policy name’,
  user,
  ‘pck_vpd.predicate’,
  ‘select,update,delete’);
end;
/
改为
begin
dbms_rls.add_policy  (
  user,
  ‘department_secrets’,
  ‘choosable policy name’,
  user,
  ‘pck_vpd.predicate’,
  ‘select,update,delete’),
  sec_relevant_cols=>’secret’;
end;
/

My _vimrc

" Use Vim settings, rather then Vi settings (much better!).
" This must be first, because it changes other options as a side effect.
set nocompatible

" sytle
colo torte

" set encoding
set encoding=utf-8
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1

" file format
set fileformats=dos,unix,mac

" allow backspacing over everything in insert mode
set backspace=indent,eol,start

" keep a backup file
set backup

" keep 100 lines of command line history
set history=100

" show the cursor position all the time
set ruler

" display incomplete commands
set showcmd       

" do incremental searching
set incsearch       

" In many terminal emulators the mouse works just fine, thus enable it.
if has(‘mouse’)
  set mouse=a
endif

" Switch syntax highlighting on, when the terminal has colors
" Also switch on highlighting the last used search pattern.
if &t_Co > 2 || has("gui_running")
  syntax on
  set hlsearch
endif

" backspace in Visual mode deletes selection
vnoremap <BS> d

" CTRL-X and SHIFT-Del are Cut
"vnoremap <C-X> "+x
vnoremap <S-Del> "+x

" CTRL-C and CTRL-Insert are Copy
"vnoremap <C-C> "+y
vnoremap <C-Insert> "+y

" CTRL-V and SHIFT-Insert are Paste
"map <C-V>        "+gP
map <S-Insert>        "+gP

" set guioptions
"set guioptions-=a

" CTRL-TAB is Next tab
noremap <C-Tab> gt
vnoremap <C-Tab> <esc>gt
inoremap <C-Tab> <esc>gt

" Shift_TAB is Previous tab
noremap <S-Tab> gT
vnoremap <S-Tab> <esc>gT
inoremap <S-Tab> <esc>gT

" Use CTRL-S for saving, also in Insert mode
noremap <C-S> :update<CR>
vnoremap <C-S> <C-C>:update<CR>
inoremap <C-S> <C-O>:update<CR>

" Don’t use ALT keys for menus.
set winaltkeys=no

" tab mapping
map <M-1> 1gt
map <M-2> 2gt
map <M-3> 3gt
map <M-4> 4gt
map <M-5> 5gt
map <M-6> 6gt
map <M-7> 7gt
map <M-8> 8gt
map <M-9> 9gt
map <M-t> :tabnew<CR>
map <M-w> :bd<CR>
map! <M-1> <esc>1gt
map! <M-2> <esc>2gt
map! <M-3> <esc>3gt
map! <M-4> <esc>4gt
map! <M-5> <esc>5gt
map! <M-6> <esc>6gt
map! <M-7> <esc>7gt
map! <M-8> <esc>8gt
map! <M-9> <esc>9gt
map! <M-t> <esc>:tabnew<CR>
map! <M-w> <esc>:bd<CR>

" display the line number
set number

" smartcase for searching
set ignorecase smartcase

" tab size
set tabstop=2

" 2 space when auto-indent
set shiftwidth=2

" replace tab with space
set expandtab

" linebreak
set linebreak

" linebreak module for asian language
set fo+=mB

" cursor keys wrap to previous/next line
set whichwrap=h,l,~,b,s,<,>,[,]

" auto indent
set autoindent

" When a bracket is inserted, briefly jump to the matching one
set showmatch

" set up statusline
set laststatus=2
set statusline=%<%f %h%m%r%=%k[%{(&fenc=="")?&enc:&fenc}%{(&bomb?",BOM":"")}] [%{&fileformat}] %-14.(%l,%c%V%) %P

"if (has("gui_running"))
" set nowrap
" set guioptions+=b
" colo torte
"else
" set wrap
" colo ron
"endif

" full screen
"au GUIEnter * simalt ~x

" set editor size
let g:editorLines=30
let g:editorColumns=125

" set editor size
function! SetScreenSize()
  let &lines=g:editorLines
  let &columns=g:editorColumns
endfunction

call SetScreenSize()

" get editor size
function! GetScreenSize()
  let g:editorLines=&lines
  let g:editorColumns=&columns
endfunction

" full screen
let g:fullScreened = 0
function! Fullscreen()
  if g:fullScreened == 0
    call GetScreenSize()
    let g:fullScreened = 1
    simalt ~x
    set go-=m
    set go-=T
    set go-=r
    set go-=b
  else
    let g:fullScreened = 0
    call SetScreenSize()
    set go+=m
    set go+=T
    set go+=r
    set go+=b
  endif
endfunction

map <F11> :call Fullscreen()<CR>

function! SaveSession()
  "set sessionoptions-=curdir
  "set sessionoptions+=sesdir
  mksession! $VIM/session.vim
  wviminfo! $VIM/session.viminfo
endfunction

map <F5> :call SaveSession()<CR>

function! LoadSession()
  source $VIM/session.vim
  rviminfo $VIM/session.viminfo
endfunction

map <F6> :call LoadSession()<CR>

set magic

" don’t highlight search result
map <F2> :noh<CR>

" for bufexplorer
map <F3> be
map! <F3> <esc>be

" share clipborad with windows
set clipboard+=unnamed

"When _vimrc is edited, reload it
autocmd! bufwritepost _vimrc source $VIM/_vimrc