/** * query 對 db 下 SQL query * * @param mixed $sql * @access protected * @return Mysqli result */ public function query($sql, $table = null) { if (Pix_Table::$_log_groups[Pix_Table::LOG_QUERY]) { Pix_Table::debug(sprintf("[%s]\t%40s", $this->_link->host_info, $sql)); } // TODO 需要 log SQL Query 功能 if ($comment = Pix_Table::getQueryComment()) { $sql = trim($sql, '; ') . ' #' . $comment; } $starttime = microtime(true); $res = $this->_link->query($sql); if ($t = Pix_Table::getLongQueryTime() and ($delta = microtime(true) - $starttime) > $t) { Pix_Table::debug(sprintf("[%s]\t%s\t%40s", $this->_link->host_info, $delta, $sql)); } if ($res === false) { if ($errno = $this->_link->errno) { switch ($errno) { case 1062: throw new Pix_Table_DuplicateException($this->_link->error, $errno); case 1406: throw new Pix_Table_DataTooLongException($this->_link->error, $errno); default: throw new Exception("SQL Error: {$this->_link->error} SQL: {$sql}"); } } } return $res; }
public function testCreateRelationHasOne() { $db = $this->getMock('Pix_Table_Db_Adapter_Abstract', array('insertOne')); Pix_Table_TableRelationTest_Table2::setDb($db); $db->expects($this->once())->method('insertOne')->with($this->isInstanceOf('Pix_Table_TableRelationTest_Table2'), array('t2_id' => 1002, 'value' => 't2_value'))->will($this->returnValue(null)); $row = new Pix_Table_Row(array('tableClass' => 'Pix_Table_TableRelationTest_Table', 'data' => array('t1_id' => 1002, 'value' => 'test_create_relation'))); $row2 = $row->create_table2(array('value' => 't2_value', 'no_this_column' => 'value')); $this->assertTrue(Pix_Table::is_a($row2, 'Pix_Table_TableRelationTest_Table2')); $this->assertEquals($row2->t2_id, $row->t1_id); $this->assertEquals($row2->value, 't2_value'); // has_many $db = $this->getMock('Pix_Table_Db_Adapter_Abstract', array('insertOne')); Pix_Table_TableRelationTest_Table3::setDb($db); $db->expects($this->once())->method('insertOne')->with($this->isInstanceOf('Pix_Table_TableRelationTest_Table3', array('t3_t1id' => '1002', 'value' => 'on')))->will($this->returnValue(5566)); $row3 = $row->create_table3s(array('value' => 'on', 'no_this_column' => 'value')); $this->assertEquals($row3->t3_id, 5566); $this->assertEquals($row3->t3_t1id, 1002); $this->assertEquals($row3->value, 'on'); // has_many empty $db = $this->getMock('Pix_Table_Db_Adapter_Abstract', array('insertOne')); Pix_Table_TableRelationTest_Table3::setDb($db); $db->expects($this->once())->method('insertOne')->with($this->isInstanceOf('Pix_Table_TableRelationTest_Table3'), array('t3_t1id' => '1002'))->will($this->returnValue(5567)); $row3 = $row->create_table3s(); $this->assertEquals($row3->t3_id, 5567); $this->assertEquals($row3->t3_t1id, 1002); $this->assertEquals($row3->value, null); }
public static function addDbFromURI($uri) { if (strpos($uri, 'mysql://') === 0) { if (!preg_match('#mysql://([^:]*):([^@]*)@([^/]*)/(.*)#', strval($uri), $matches)) { throw new Exception("wrong mysql URI format, must be mysql://{user}:{password}@{host}/{db}"); } $db = new StdClass(); $db->host = $matches[3]; $db->username = $matches[1]; $db->password = $matches[2]; $db->dbname = $matches[4]; $config = new StdClass(); $config->master = $config->slave = $db; Pix_Table::setDefaultDb(new Pix_Table_Db_Adapter_MysqlConf(array($config))); } elseif (strpos($uri, 'pgsql://') === 0) { if (!preg_match('#pgsql://([^:]*):([^@]*)@([^/:]*):?([0-9]*)?/(.*)#', strval($uri), $matches)) { throw new Exception("wrong pgsql URI format, must be pgsql://{user}:{password}@{host}/{db}"); } $options = array('host' => $matches[3], 'user' => $matches[1], 'password' => $matches[2], 'dbname' => $matches[5]); if ($matches[4]) { $options['port'] = $matches[4]; } Pix_Table::setDefaultDb(new Pix_Table_Db_Adapter_PgSQL($options)); } elseif (strpos($uri, 'sqlite://') === 0) { $file = substr($uri, strlen('sqlite://')); Pix_Table::setDefaultDb(new Pix_Table_Db_Adapter_Sqlite($file)); } else { throw new Exception("add DB failed, unknown uri {$uri}"); } }
public function main($argv) { Pix_Table::$_save_memory = true; list(, $type, $year, $month) = $argv; if (!in_array($type, array('company', 'bussiness', 'company-continue', 'bussiness-continue'))) { return $this->wrong_argv(); } if (in_array($type, array('company', 'bussiness'))) { $year = intval($year); $month = intval($month); if (!intval($year) or !intval($month)) { return $this->wrong_argv(); } } if ('company' == $type) { $ids = Crawler::crawlerMonth($year, $month); $ids = array_unique($ids); file_put_contents('ids', implode("\n", $ids)); foreach ($ids as $id) { $u = Updater::update($id); if ($u) { $u->updateSearch(); } } } elseif ('company-continue' == $type) { $ids = explode("\n", file_get_contents('ids')); $pos = array_search($year, $ids); var_dump($pos); if (false === $pos) { return $this->wrong_argv(); } foreach (array_slice($ids, $pos - 1) as $id) { $u = Updater::update($id); if ($u) { $u->updateSearch(); } } } else { $ids = Crawler::crawlerBussiness($year, $month); $ids = array_unique($ids); file_put_contents('ids', implode("\n", $ids)); foreach ($ids as $id) { $u = Updater::updateBussiness($id); if ($u) { $u->updateSearch(); } } } }
/** * insertOne 從 db 上增加一筆資料 * * @param Pix_Table $table * @param array|string $keys_values * @access public * @return void */ public function insertOne($table, $keys_values) { if (!is_array($keys_values)) { $keys_values = array(); } $sql = 'INSERT INTO ' . $this->column_quote($table->getTableName()); $keys = $values = array(); foreach ($keys_values as $key => $value) { if (is_null($value)) { continue; } $keys[] = $this->column_quote($key); $values[] = $this->quoteWithColumn($table, $value, $key); } if ($keys) { $sql .= '(' . implode(', ', $keys) . ') VALUES (' . implode(', ', $values) . ')'; } else { $sql .= ' DEFAULT VALUES '; } $this->query($sql); return $this->getLastInsertId($table); }
/** * declare a new empty Pix Table * * @static * @access public * @return Pix_Table */ public static function newEmptyTable($table_name = null) { if (is_null($table_name)) { while (true) { $table_name = 'Pix_Table_EmptyTable_' . crc32(uniqid()); if (!class_exists($table_name, false)) { break; } } } if (class_exists($table_name, false)) { throw new Pix_Table_Exception("newEmptyTable failed, {$table_name} is existed."); } // XXX: In Pix Table, a Table is mapping to a PHP class. If you want dynamically new a table, // you must declare a new Pix_Table class. // class_alias doesn't worked here. eval("class {$table_name} extends Pix_Table {}"); return Pix_Table::getTable($table_name); }
public function testNullOrFalse() { Pix_Table::$_save_memory = false; $cache = new Pix_Table_TableCacheTest_Cache(); Pix_Table::setCache($cache); $table = Pix_Table::getTable('Pix_Table_TableCacheTest_User'); $table->enableTableCache(); // 什麼都沒有是 false $this->assertTrue($table->getRowFromCache(6) === false); // cacheRow null 後是 null (表示被刪除) $table->cacheRow(7, null); $this->assertTrue($table->getRowFromCache(7) === null); // cacheRow false 後是 false $table->cacheRow(8, false); $this->assertTrue($table->getRowFromCache(8) === false); }
public function autocomplete($name, $args2, $args3) { $res = array(); if (preg_match('#^(.*)::(.*)$#', $name, $matches)) { $methods = get_class_methods($matches[1]); foreach ($methods as $m) { if ($matches[2] === '' or strpos($m, $matches[2]) === 0) { $res[] = $matches[1] . '::' . $m . '()'; } } } elseif (preg_match('#\\$([^$]*)->([^>]*)$#', readline_info('line_buffer'), $matches)) { $obj = self::$_vars[$matches[1]]; if (!is_object($obj) or ($class = get_class($obj)) === false) { return null; } if (is_a($obj, 'Pix_Table_Row')) { // columns foreach (array_keys($obj->getTable()->_columns) as $m) { if ($matches[2] === '' or strpos($m, $matches[2]) === 0) { $res[] = $m; } } // relations foreach (array_keys($obj->getTable()->_relations) as $m) { if ($matches[2] === '' or strpos($m, $matches[2]) === 0) { $res[] = $m; } } // aliases if ($obj->getTable()->_aliases) { foreach (array_keys($obj->getTable()->_aliases) as $m) { if ($matches[2] === '' or strpos($m, $matches[2]) === 0) { $res[] = $m; } } } // hook if ($obj->getTable()->_hooks) { foreach (array_keys($obj->getTable()->_hooks) as $name) { if ($matches[2] === '' or stripos($name, $matches[2]) === 0) { $res[] = $name; } } } // Table Row Helper foreach (array_keys($obj->getTable()->getHelperManager('row')->getMethods()) as $name) { if ($matches[2] === '' or stripos($name, $matches[2]) === 0) { $res[] = $name . '()'; } } // Table Static Helper foreach (array_keys(Pix_Table::getStaticHelperManager('row')->getMethods()) as $name) { if ($matches[2] === '' or stripos($name, $matches[2]) === 0) { $res[] = $name . '()'; } } } $methods = get_class_methods($class); foreach ($methods as $m) { if ($matches[2] === '' or strpos($m, $matches[2]) === 0) { $res[] = $m . '()'; } } } else { foreach (self::findMatch($name) as $o) { $res[] = $o; } } if (count($res) == 0) { return null; } return $res; }
/** * createTable 將 $table 建立進資料庫內 * * @param Pix_Table $table * @access public * @return void */ public function createTable($table) { $sql = "CREATE TABLE \"" . $table->getTableName() . '"'; $types = array('bigint', 'tinyint', 'int', 'varchar', 'char', 'text', 'float', 'double', 'binary'); $primarys = is_array($table->_primary) ? $table->_primary : array($table->_primary); $pk_isseted = false; foreach ($table->_columns as $name => $column) { $s = $this->column_quote($name) . ' '; $db_type = in_array($column['type'], $types) ? $column['type'] : 'text'; if ($column['unsigned'] and !$column['auto_increment']) { $s .= 'UNSIGNED '; } if ($column['auto_increment']) { $s .= 'SERIAL'; } elseif ('int' == $db_type) { $s .= 'INTEGER'; } elseif ('binary' == $db_type) { $s .= 'BYTEA'; } else { $s .= strtoupper($db_type); } if (in_array($db_type, array('varchar', 'char'))) { if (!$column['size']) { throw new Exception('you should set the option `size`'); } $s .= '(' . $column['size'] . ')'; } $s .= ' '; if ($column['auto_increment']) { if ($primarys[0] != $name or count($primarys) > 1) { throw new Exception('SQLITE 的 AUTOINCREMENT 一定要是唯一的 Primary Key'); } $s .= ' PRIMARY KEY '; $pk_isseted = true; } if (isset($column['default'])) { $s .= 'DEFAULT ' . $this->quoteWithColumn($table, $column['default'], $name) . ' '; } $column_sql[] = $s; } if (!$pk_isseted) { $s = 'PRIMARY KEY '; $index_columns = array(); foreach (is_array($table->_primary) ? $table->_primary : array($table->_primary) as $pk) { $index_columns[] = $this->column_quote($pk); } $s .= '(' . implode(', ', $index_columns) . ")\n"; $column_sql[] = $s; } $sql .= " (\n" . implode(", \n", $column_sql) . ") \n"; // CREATE TABLE $this->query($sql); foreach ($table->getIndexes() as $name => $options) { if ('unique' == $options['type']) { $s = 'CREATE UNIQUE INDEX '; } else { $s = 'CREATE INDEX '; } $columns = $options['columns']; $s .= $this->column_quote($table->getTableName() . '_' . $name) . ' ON ' . $this->column_quote($table->getTableName()); $index_columns = array(); foreach ($columns as $column_name) { $index_columns[] = $this->column_quote($column_name); } $s .= '(' . implode(', ', $index_columns) . ') '; $this->query($s); } }
/** * 如果在 __construct 呼叫 $this->xxx() 會 failed 的測試 * @expectedException Pix_Table_Exception */ public function testGetTableConstructFailed() { Pix_Table::getTable('Pix_Table_TableTest_TableContstructFailed'); }
<?php ini_set('memory_limit', '256m'); include __DIR__ . '/../init.inc.php'; Pix_Table::$_save_memory = true; Pix_Table::addStaticResultSetHelper('Pix_Array_Volume'); class Dumper { protected $unit_types = array(); public function getType($id) { if (!array_key_exists($id, $this->unit_types)) { $start = floor($id / 10000) * 10000; $end = $start + 10000; $this->unit_types = Unit::search("`id` >= {$start} AND `id` < {$end}")->toArray('type'); } return $this->unit_types[$id]; } public function dump() { $columns = array(); foreach (ColumnGroup::search(1) as $columngroup) { $columns[$columngroup->id] = $columngroup->name; } $delta = 10000000; for ($i = 0; $i * $delta < 99999999; $i++) { $start = $i * $delta; $end = $start + $delta - 1; $tmpname1 = tempnam('', ''); $tmpname2 = tempnam('', ''); $file_name1 = 'files/' . str_pad($i * $delta, 8, '0', STR_PAD_LEFT) . '.json.gz';
/** * fetch 取得符合 $search 條件的資料 * * @param Pix_Table $table * @param Pix_Table_Search $search * @param string|array $select_columns * @access public * @return void */ public function fetch($table, $search, $select_columns = '*') { $db = $this->_getDb(); $condictions = $search->getSearchCondictions(); if (count($condictions) == 0) { // 完全沒有條件就是 scan table $options = array(); $options['TableName'] = $table->getTableName(); // 加上指定 column if ('*' != $select_columns) { $options['AttributesToGet'] = $select_columns; } $response = $db->scan($options); } elseif (count($condictions) == 1) { // 只給一個條件的話只能是 HashKey $primary_keys = $table->getPrimaryColumns(); // 只能是 map if ('map' != $condictions[0][0]) { throw new Pix_Table_Exception("不支援的 search 條件"); } // 只能是 Primary Key 的第一個 if ($primary_keys[0] != $condictions[0][1]) { throw new Pix_Table_Exception("不支援的 search 條件"); } $options = array(); $options['TableName'] = $table->getTableName(); $options['HashKeyValue'] = array($this->_getColumnType($table, $primary_keys[0]) => $condictions[0][2]); // 加上 Limit if (!is_null($limit = $search->limit())) { $options['Limit'] = $limit; } // 加上 after or before if ($row = $search->after()) { $options['RangeKeyCondition'] = array('ComparisonOperator' => AmazonDynamoDB::CONDITION_GREATER_THAN, 'AttributeValueList' => array(array($this->_getColumnType($table, $primary_keys[1]) => $row->{$primary_keys[1]}))); } elseif ($row = $search->before()) { $options['RangeKeyCondition'] = array('ComparisonOperator' => AmazonDynamoDB::CONDITION_LESS_THAN, 'AttributeValueList' => array(array($this->_getColumnType($table, $primary_keys[1]) => $row->{$primary_keys[1]}))); $options['ScanIndexForward'] = false; } // 加上指定 column if ('*' != $select_columns) { $options['AttributesToGet'] = $select_columns; } $response = $db->query($options); } else { throw new Pix_Table_Exception("不支援的 search 條件"); } if (200 != $response->status) { throw new Pix_Table_Exception("AmazonDynamoDB: " . $get_response->body->Message); } $ret = array(); foreach ($response->body->Items[0] as $item) { $row = array(); foreach ($table->_columns as $name => $col) { if ($item->{$name}) { $row[$name] = strval($item->{$name}->S); } } $ret[] = $row; } return $ret; }
public function testUpdate() { $db = $this->getMock('Pix_Table_Db_Adapter_Abstract', array('updateOne')); $table = Pix_Table::getTable('Pix_Table_TableRowTest_Table'); $row = new Pix_Table_Row(array('tableClass' => 'Pix_Table_TableRowTest_Table', 'data' => array('t1_id' => 1005, 'value' => 'abc'))); // array $db->expects($this->once())->method('updateOne')->with($this->isInstanceOf(get_class($row)), array('value' => '9'))->will($this->returnValue(null)); Pix_Table_TableRowTest_Table::setDb($db); $row->update(array('value' => '9')); $this->assertEquals($row->value, '9'); // string $db = $this->getMock('Pix_Table_Db_Adapter_Abstract', array('updateOne', 'fetchOne', 'support')); $db->expects($this->any())->method('support')->with($this->logicalOr('immediate_consistency', 'force_master'))->will($this->returnValue(true)); $db->expects($this->once())->method('updateOne')->with($this->isInstanceOf(get_class($row)), 'value = value + 1')->will($this->returnValue(null)); $db->expects($this->once())->method('fetchOne')->with($this->isInstanceOf('Pix_Table_TableRowTest_Table', array(1005)))->will($this->returnValue(array('t1_id' => 1005, 'value' => '10'))); Pix_Table_TableRowTest_Table::setDb($db); $row->update("value = value + 1"); $this->assertEquals($row->value, 10); }
/** * getRelationForeignTable 取得 relation 對應的 table * * @param string $relation relation 名稱 * @static * @access public * @return Pix_Table 對應的 table */ public static function getRelationForeignTable($relation) { $table = self::getTable(); if (!array_key_exists($relation, $table->_relations)) { throw new Pix_Table_Exception("{$table->getClass()} 找不到 {$relation} 這個 relation"); } $relation_data = $table->_relations[$relation]; if (!array_key_exists('type', $relation_data)) { throw new Pix_Table_Exception("{$table->getClass()}->{$relation} 沒有指定 Table Type"); } $table_name = $relation_data['type']; return Pix_Table::getTable($table_name); }
/** * get Pix_Table object from db schema * * @param string $db_table_name * @param string $pix_table_name * @access public * @return Pix_Table */ public function getTableFromDb($db_table_name, $pix_table_name = null) { $table = Pix_Table::newEmptyTable($pix_table_name); $table->_name = $db_table_name; $table->setDb($this); $res = $this->query("SP_PKEYS " . $this->column_quote($db_table_name)); $table->_primary = array(); while ($row = $res->fetch_object()) { $table->_primary[] = $row->COLUMN_NAME; } $res->free_result(); $res = $this->query("SP_COLUMNS " . $this->column_quote($db_table_name)); // http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.sprocs/html/sprocs/sprocs225.htm $data_types = array(1 => 'char', 3 => 'int', 8 => 'double', 6 => 'float', 4 => 'int', 2 => 'int', 7 => 'double', 5 => 'smallint', 12 => 'varchar', -5 => 'bigint', -2 => 'binary', 9 => 'string', -1 => 'text', -4 => 'blob'); while ($row = $res->fetch_object()) { $field = $row->COLUMN_NAME; $table->_columns[$field] = array(); if (!array_key_exists($row->DATA_TYPE, $data_types)) { throw new Pix_Table_Exception("Unknown DATA_TYPE: " . $row->DATA_TYPE); } $table->_columns[$field]['type'] = $data_types[$row->DATA_TYPE]; if ($row->TYPE_NAME == 'int identity') { $table->_columns[$field]['auto_increment'] = 1; } // check default if (!is_null($row->COLUMN_DEFAULT)) { $table->_columns[$field]['default'] = $row->COLUMN_DEFAULT; } } $res->free_result(); return $table; }
/** * testStaticTableHelper test add Table Helper to all Pix_Table */ public function testStaticTableHelper() { Pix_Table::addStaticTableHelper('Pix_Table_TableHelperTest_Helper', array('static_table_test')); Pix_Table_TableHelperTest_Table::setData(uniqid()); $uniqid = uniqid(); $this->assertEquals(Pix_Table_TableHelperTest_Table::static_table_test($uniqid), 'StaticTableHelper-' . Pix_Table_TableHelperTest_Table::getData() . '-' . $uniqid); }
<?php error_reporting(E_ALL ^ E_STRICT ^ E_NOTICE); include __DIR__ . '/stdlibs/pixframework/Pix/Loader.php'; set_include_path(__DIR__ . '/stdlibs/pixframework/' . PATH_SEPARATOR . __DIR__ . '/models' . PATH_SEPARATOR . __DIR__ . '/Dropbox-master'); Pix_Loader::registerAutoLoad(); if (file_exists(__DIR__ . '/config.php')) { include __DIR__ . '/config.php'; } // TODO: 之後要搭配 geoip date_default_timezone_set('Asia/Taipei'); if (!getenv('MYSQL_DATABASE_URL')) { die('need MYSQL_DATABASE_URL'); } if (!preg_match('#mysql://([^:]*):([^@]*)@([^/]*)/(.*)#', strval(getenv('MYSQL_DATABASE_URL')), $matches)) { die('mysql only'); } $db = new StdClass(); $db->host = $matches[3]; $db->username = $matches[1]; $db->password = $matches[2]; $db->dbname = $matches[4]; $config = new StdClass(); $config->master = $config->slave = $db; Pix_Table::setDefaultDb(new Pix_Table_Db_Adapter_MysqlConf(array($config)));
<?php include __DIR__ . '/libs/pixframework/Pix/Loader.php'; set_include_path(__DIR__ . '/libs/pixframework' . PATH_SEPARATOR . __DIR__ . '/models'); Pix_Loader::registerAutoload(); if (file_exists(__DIR__ . '/config.php')) { include __DIR__ . '/config.php'; } else { if (getenv('DATABASE_URL')) { if (preg_match('#postgres://([^:]*):([^@]*)@([^/]*)/(.*)#', strval(getenv('DATABASE_URL')), $matches)) { $user = $matches[1]; $pass = $matches[2]; $host = $matches[3]; $dbname = $matches[4]; Pix_Table::setDefaultDb(new Pix_Table_Db_Adapter_PgSQL(array('user' => $user, 'password' => $pass, 'host' => $host, 'dbname' => $dbname))); } } } date_default_timezone_set('Asia/Taipei');
<?php include __DIR__ . '/init.php'; Pix_Table::$_save_memory = true; $last_time = intval(KeyValue::get('snapshot_at')); // dump count while (true) { $min_time = RankData::search("`time` > {$last_time}")->min('time')->time; if (!$min_time) { break; } $month_start = mktime(0, 0, 0, date('m', $min_time), 1, date('Y', $min_time)); $month_end = strtotime('+1 month', $month_start); $filename = 'ptthot-' . date('Ym', $month_start) . '.csv.gz'; $temp = tmpfile(); $meta_data = stream_get_meta_data($temp); $tmp_filename = $meta_data['uri']; $stream = gzopen($tmp_filename, 'w'); fwrite($stream, "#board,timestamp,count\n"); foreach (RankData::search("`time` >= {$month_start} AND `time` < {$month_end}")->order(array('board', 'time'))->volumemode(10000) as $rankdata) { $last_time = max($last_time, $rankdata->time); fwrite($stream, "{$rankdata->board},{$rankdata->time},{$rankdata->count}\n"); } fclose($stream); DropboxLib::putFile($tmp_filename, $filename); fclose($temp); KeyValue::set('snapshot_at', $last_time); } //dump titlehistory $filename = 'ptthot-title.csv.gz'; $temp = tmpfile();
public function __call($func, $args) { if ($this->getTable()->getHelperManager('resultset')->hasMethod($func)) { array_unshift($args, $this); return $this->getTable()->getHelperManager('resultset')->callHelper($func, $args); } elseif (Pix_Table::getStaticHelperManager('resultset')->hasMethod($func)) { array_unshift($args, $this); return Pix_Table::getStaticHelperManager('resultset')->callHelper($func, $args); } throw new Pix_Table_Exception("找不到 function {$func}"); }
/** * dropTable 從資料庫內移除 $table 這個 Table * * @param Pix_Table $table * @access public * @return void */ public function dropTable($table) { if (!Pix_Setting::get('Table:DropTableEnable')) { throw new Pix_Table_Exception("要 DROP TABLE 前請加上 Pix_Setting::set('Table:DropTableEnable', true);"); } $sql = "DROP TABLE " . $this->column_quote($table->getTableName()); return $this->query($sql, $table); }
/** * refreshRowData 去資料庫更新這一個 row 的資料 * * @access public * @return void */ public function refreshRowData() { $db = $this->getRowDb(); $this->_relation_data = array(); // 若 db 不支援 immediate_consistency ,就不需要去 db 更新資料了 if (!$db->support('immediate_consistency')) { return; } // XXX: 保險起見這邊強制從 master 抓 if ($db->support('force_master')) { $old_force_master = Pix_Table::$_force_master; Pix_Table::$_force_master = true; } if ($row = $db->fetchOne($this->getTable(), $this->getPrimaryValues())) { $this->_data = $this->_orig_data = $row; } if ($db->support('force_master')) { Pix_Table::$_force_master = $old_force_master; } }
public function query($sql, $table = null) { // 判斷要用 Master 還是 Slave $type = 'master'; if (!Pix_Table::$_force_master and preg_match('#^SELECT #', strtoupper($sql))) { $type = 'slave'; } if (Pix_Setting::get('Table:ExplainFileSortEnable')) { if (preg_match('#^SELECT #', strtoupper($sql))) { $res = $this->_getLink($type)->query("EXPLAIN {$sql}"); $row = $res->fetch_assoc(); if (preg_match('#Using filesort#', $row['Extra'])) { trigger_error("Using Filesort Query {$sql}", E_USER_WARNING); } $res->free_result(); } } if (Pix_Setting::get('Table:SQLNoCache')) { if (preg_match('#^SELECT #', strtoupper($sql))) { $sql = 'SELECT SQL_NO_CACHE ' . substr($sql, 7); } } // 加上 Query Comment if ($comment = Pix_Table::getQueryComment()) { $sql = trim($sql, '; ') . ' #' . $comment; } for ($i = 0; $i < 3; $i++) { if (!($link = $this->_getLink($type))) { throw new Exception('找不到 Link'); } $starttime = microtime(true); $res = $link->query($sql); $this->insert_id = $link->insert_id; $delta = microtime(true) - $starttime; if (array_key_exists(Pix_Table::LOG_QUERY, Pix_Table::$_log_groups) and Pix_Table::$_log_groups[Pix_Table::LOG_QUERY]) { Pix_Table::debug(sprintf("[%s-%s](%f)%s", strval($link->host_info), $type, $delta, $sql)); } elseif ($t = Pix_Table::getLongQueryTime() and $delta > $t) { Pix_Table::debug(sprintf("[%s-%s](%f)%s", strval($link->host_info), $type, $delta, $sql)); } if ($res === false) { if ($errno = $link->errno) { $message = (is_null($table) ? '' : "Table: {$table->getClass()}") . "SQL Error: ({$errno}){$link->error} " . substr($sql, 0, 128); switch ($errno) { case 1146: throw new Pix_Table_TableNotFoundException($message); case 1062: throw new Pix_Table_DuplicateException((is_null($table) ? '' : "(Table: {$table->getClass()})") . $link->error, $errno); case 1406: throw new Pix_Table_DataTooLongException($message); case 2006: // MySQL server gone away // MySQL server gone away case 2013: // Lost connection to MySQL server during query trigger_error("Pix_Table " . $message, E_USER_WARNING); $this->resetConnect(); continue 2; } } throw new Pix_Table_Exception($message); } if ($link->warning_count) { $e = $link->get_warnings(); do { if (1592 == $e->errno) { continue; } if (Pix_Table::$_throw_incorrect_string_exception and 1366 == $e->errno) { throw new Pix_Table_IncorrectStringException($e->message); } trigger_error("Pix_Table " . (is_null($table) ? '' : "Table: {$table->getClass()}") . "SQL Warning: ({$e->errno}){$e->message} " . substr($sql, 0, 128), E_USER_WARNING); } while ($e->next()); } return $res; } throw new Pix_Table_Exception("query 三次失敗"); }
<?php include __DIR__ . '/init.inc.php'; if ($_SERVER['argv'][1] == '-d') { Pix_Table::enableLog(Pix_Table::LOG_QUERY); } Pix_Prompt::init();