00001 <?php
00012 class SQL_Generator
00013 {
00014 var $db;
00015 var $page;
00016
00022 function SQL_Generator(&$page)
00023 {
00024 $this->db =& Registry::get('pronto:db:main');
00025 $this->page =& $page;
00026 }
00027
00038 function enumerate($params, $set_vars=false)
00039 {
00040
00041
00042 extract($params, EXTR_OVERWRITE);
00043
00044 assert_type($exprs, 'array');
00045 assert_type($gexprs, 'array');
00046 foreach($exprs as $k=>$v) $select .= ",$v \"$k\"";
00047 foreach($gexprs as $k=>$v) $select .= ",$v \"$k\"";
00048
00049 if(substr($select, 0, 1) == ',') $select = substr($select, 1);
00050
00051
00052
00053 list($w_sql,$w_args,$h_sql,$h_args) = $this->filter($exprs, $gexprs);
00054
00055
00056 if(is_array($where)) {
00057 foreach($where as $v) $w_sql .= " AND ($v)";
00058 } else if(!empty($where)) {
00059 $w_sql .= " AND ($where)";
00060 }
00061
00062 if(!empty($where_args)) $w_args = array_merge($w_args, $where_args);
00063
00064
00065 if(is_array($having)) {
00066 foreach($having as $v) $h_sql .= " AND ($v)";
00067 } else if(!empty($having)) {
00068 $h_sql .= " AND ($having)";
00069 }
00070
00071
00072 $args = empty($h_args) ? $w_args : array_merge($w_args, $h_args);
00073
00074
00075 $sort_sql = $this->sort($order, $exprs);
00076 $page_sql = $this->paginate($limit);
00077
00078
00079 if($this->db->type == 'mysql') $select = "SQL_CALC_FOUND_ROWS $select";
00080 $sql = $this->db->build_sql($select, $from, $w_sql, $group_by, $h_sql, $sort_sql, $page_sql);
00081 $data = $this->db->get_all($sql, $args);
00082
00083
00084 if($this->db->type == 'mysql') {
00085 $ttlrows = $this->db->get_value("SELECT FOUND_ROWS()");
00086 } else {
00087 $ttlrows = $this->db->get_value($this->db->build_sql("COUNT(*)", $from, $w_sql, $group_by, $h_sql), $args);
00088 }
00089
00090 if($set_vars) {
00091 $this->page->template->set('data', $data);
00092 $this->page->template->set('totalrows', $ttlrows);
00093 $this->page->template->set('curpage', $this->page->param('p_p', 1));
00094 $this->page->template->set('perpage', $this->page->param('p_pp', $limit));
00095 }
00096
00097
00098 return array($data, $ttlrows, $this->page->param('p_p', 1), $this->page->param('p_pp', $limit));
00099 }
00100
00113 function filter($exprs=array(), $gexprs=array())
00114 {
00115 $where = array('sql'=>array(), 'args'=>array());
00116 $having = array('sql'=>array(), 'args'=>array());
00117 foreach($_REQUEST as $k=>$v) {
00118 $args = array();
00119 $sql = array();
00120
00121 if($v === '') continue;
00122 if(!preg_match('|^f_[dts]_|', $k)) continue;
00123 $t = substr($k, 2, 1);
00124 $k = substr($k, 4);
00125
00126 if(!preg_match('|^[A-z0-9_-]+$|', $k)) continue;
00127 switch($t) {
00128 case 'd': $coltype = 'date'; break;
00129 case 's': $coltype = 'select'; break;
00130 case 't':
00131 default: $coltype = 'text';
00132 }
00133
00134
00135
00136 if(isset($exprs[$k])) {
00137 $s = $exprs[$k];
00138 $t = 'where';
00139 } else if(isset($gexprs[$k])) {
00140 $s = $gexprs[$k];
00141 $t = 'having';
00142 } else {
00143
00144 $s = "\"$k\"";
00145 $t = 'where';
00146 }
00147
00148 $range = explode('<>', $v);
00149 if(count($range) == 2) {
00150
00151 $sql[] = "($s>='%s' AND $s<='%s')";
00152 $args[] = $range[0];
00153 $args[] = $range[1];
00154 } else if(strlen($v) == 1) {
00155
00156
00157
00158 $sql[] = is_numeric($v) ? "$s='%s'" : "$s LIKE '%%s%'";
00159 $args[] = $v;
00160 } else {
00161
00162 $chop = 0;
00163 switch(substr($v, 0, 1)) {
00164 case '=':
00165 $s .= '='; $chop = 1;
00166 break;
00167 case '>':
00168 switch($v{1}) {
00169 case '=': $s .= '>='; $chop = 2; break;
00170 default: $s .= '>'; $chop = 1; break;
00171 }
00172 break;
00173 case '<':
00174 switch($v{1}) {
00175 case '=': $s .= '<='; $chop = 2; break;
00176 default: $s .= '<'; $chop = 1; break;
00177 }
00178 break;
00179 default:
00180 $s .= ' LIKE ';
00181 }
00182 $v = substr($v, $chop);
00183 if($chop || is_numeric($v)) {
00184 $s .= "'%s'";
00185 } else {
00186 $s .= "'%%s%'";
00187 }
00188 $sql[] = $s;
00189 $args[] = $v;
00190
00191
00192 if($coltype == 'date' && $chop) {
00193
00194 $s = isset($exprs[$k]) ? $exprs[$k] : "\"$k\"";
00195 $s .= "!='0000-00-00'";
00196 $sql[] = $s;
00197 }
00198 }
00199 switch($t) {
00200 case 'where':
00201 $where['sql'] = array_merge($where['sql'], $sql);
00202 $where['args'] = array_merge($where['args'], $args);
00203 break;
00204 case 'having':
00205 $having['sql'] = array_merge($having['sql'], $sql);
00206 $having['args'] = array_merge($having['args'], $args);
00207 }
00208 }
00209
00210
00211 $where['sql'][] = '1=1';
00212
00213 $final = array(implode(' AND ', $where['sql']), $where['args']);
00214 if(!empty($having['sql'])) {
00215 $final[] = implode(' AND ', $having['sql']);
00216 $final[] = $having['args'];
00217 }
00218
00219 return $final;
00220 }
00221
00233 function sort($default, $exprs=array())
00234 {
00235 $cols = $sortsql = array();
00236 $field = $this->page->param('s_f', '');
00237 if($field) {
00238 $dir = $this->page->param('s_d', 'ASC');
00239 $cols = array(array('field'=>$field, 'dir'=>$dir));
00240 } else {
00241
00242 foreach(explode(',', $default) as $pair) {
00243 $pair = trim($pair);
00244 if(empty($pair)) continue;
00245 $p = explode(' ', $pair);
00246 $cols[] = array('field'=>$p[0], 'dir'=>isset($p[1]) ? $p[1] : 'ASC');
00247 }
00248 }
00249
00250 foreach($cols as $c) {
00251
00252
00253 if(isset($exprs[$c['field']])) {
00254 $s = $exprs[$c['field']];
00255 } else {
00256
00257 $p = explode('.', $c['field']);
00258 if(isset($p[1])) {
00259 $s = $p[0].'."'.$p[1].'"';
00260 } else {
00261 $s = "\"{$c['field']}\"";
00262 }
00263 }
00264 $sortsql[] = "$s {$c['dir']}";
00265 }
00266
00267 return join(',', $sortsql);
00268 }
00269
00277 function paginate($perpage=50)
00278 {
00279 if($perpage == 0) return '';
00280
00281 $page = $this->page->param('p_p', 1);
00282 $perpage = $this->page->param('p_pp', $perpage);
00283 $offset = max(0,($page-1) * $perpage);
00284
00285 return "$perpage OFFSET $offset";
00286 }
00287
00288 }
00289
00290 ?>