Wednesday, 20 February 2013

Calculate supernets to /16 in Oracle SQL

This bit of SQL calculates all the supernet addresses (to /16) for a given IP address (and mask) in Oracle. Supernet addresses are the 'containing' IP Addresses based on powers of 2, so a /30 address covers 2(32-30) addresses (or 4 IPs). A /26 address covers 2(32-26) addresses (64 IPs). This works on Oracle 9, 10 and 11. If your version does not support regexp_replace there are some commented fields that utilise some instr calls.
select 
lvl supernet_mask, 
ip, 
regexp_substr(ip,'^\d+\.\d+\.') || resl2 || '.' || resl supernet
from
(
select 
  lvl, ip, mask, q3,q4,
  case when lvl > 24 then
    null
  else 
    0 
  end supernet
  , 
  floor(q4/(power(2,32-lvl))) * power(2,32-lvl) resl 
  , 
  CASE WHEN lvl <= 24 then 
    floor(q3/(power(2,24-lvl))) * power(2,24-lvl) 
  ELSE 
    Q3
  END resl2
from
(
select lvl, ip, mask
, to_number(regexp_substr(ip,'\d+',1)) q1
, to_number(regexp_replace(ip,'(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})','\2')) q2
, to_number(regexp_replace(ip,'(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})','\3')) q3
, to_number(regexp_replace(ip,'(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})','\4')) q4
/* -- if your version does not support regexp_replace
, to_number(substr(ip,1,instr(ip,'.',1,1)-1)) q1
, to_number(substr(ip,instr(ip,'.',1,1)+1,instr(ip,'.',1,2 )-instr(ip,'.',1,1)-1 ))  q2
, to_number(substr(ip,instr(ip,'.',1,2)+1,instr(ip,'.',1,3 )-instr(ip,'.',1,2)-1 )) q3
, to_number(substr(ip,instr(ip,'.',1,3)+1)) q4
*/
from 
(
select 33 - level lvl,'203.63.104.108' ip,30 mask from dual connect by level <= 17 union
select 33 - level lvl,'203.63.104.12' ip,30 mask from dual connect by level <= 17 union
select 33 - level lvl,'203.63.104.124' ip,30 mask from dual connect by level <= 17 union
select 33 - level lvl,'203.63.104.144' ip,30 mask from dual connect by level <= 17 
) x
where mask >= lvl
) xx order by ip, lvl desc
) xxx

Sunday, 3 February 2013

This Javascript function will filter a table according to a RegEx match with an input string. It does this by looping through each row of the table and hiding it if nothing matches. This is a pretty useful bit of code when you are presented report outputs as html tables, your user likes to chop and change conditions, and the query itself is a little slow.
//takes the tableid, and the filterstring and loops through the table
//doing a regex match using the filterString. if line matches, the <tr> is shown
// but if no match anywhere on the line, it is hidden.  
// Andrew Cave 04/02/2013
// andrew.cave.blogging@gmail.com
function filterTable(tableID,filterString){
t = document.getElementById(tableID);
if(typeof t=='undefined'){return;}//exit if the table hasn't been created yet
tbod = t.tBodies[0];
rows = tbod.rows;
rowct = rows.length;
filterString = trim(filterString);
filterString=(filterString.length==0)?'.*':filterString; //empty strings return all records
re = new RegExp(trim(filterString),"i");

for(i=0;i < rowct;i++){
cells=rows[i].cells;
cellct=cells.length;
hideme = 1; //start with hideme being true
for(j=0;j < cellct;j++){
	var td = cells[j].innerHTML;
	if(td.match(re)){ //checking for a match
		hideme=0;
		break;
	}
}
if(hideme){
	$(rows[i]).hide();
} else {
	$(rows[i]).show();
}
}
}