0011903_v6.patch

Administrator Admin, 2009-09-21 15:12

Download (17.3 KB)

View differences:

tests/t3lib/cache/backend/t3lib_cache_backend_dbbackendtestcase.php (Arbeitskopie)
63 63
	protected $backend;
64 64

  
65 65
	protected $testingCacheTable;
66
	protected $testingTagsTable;
66 67

  
67 68
	/**
68 69
	 * Sets up this testcase
......
72 73
	 */
73 74
	public function setUp() {
74 75
		$this->testingCacheTable = 'test_cache_dbbackend';
76
		$this->testingTagsTable = 'test_cache_dbbackend_tags';
75 77

  
76 78
		$GLOBALS['TYPO3_DB']->sql_query('CREATE TABLE ' . $this->testingCacheTable . ' (
77 79
			id int(11) unsigned NOT NULL auto_increment,
......
85 87
		) ENGINE=InnoDB;
86 88
		');
87 89

  
90
		$GLOBALS['TYPO3_DB']->sql_query('CREATE TABLE ' . $this->testingTagsTable . ' (
91
			id int(11) unsigned NOT NULL auto_increment,
92
			identifier varchar(128) DEFAULT \'\' NOT NULL,
93
			tag varchar(128) DEFAULT \'\' NOT NULL,
94
			PRIMARY KEY (id),
95
			KEY cache_id (identifier),
96
			KEY cache_tag (tag)
97
		) ENGINE=InnoDB;
98
		');
99

  
88 100
		$this->backend = t3lib_div::makeInstance(
89 101
			't3lib_cache_backend_DbBackend',
90
			array('cacheTable' => $this->testingCacheTable)
102
			array(
103
				'cacheTable' => $this->testingCacheTable,
104
				'tagsTable' => $this->testingTagsTable,
105
			)
91 106
		);
92 107
	}
93 108

  
......
213 228

  
214 229
		$entriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
215 230
			'*',
216
			$this->testingCacheTable,
231
			$this->testingTagsTable,
217 232
			'identifier = \'' . $entryIdentifier . '\''
218 233
		);
219 234

  
220
		$tags = explode(',', $entriesFound[0]['tags']);
235
		$tags = array();
221 236

  
222
		$this->assertTrue(is_array($tags) && count($entriesFound) > 0, 'The tags do not exist.');
237
		foreach ($entriesFound as $entry) {
238
			$tags[] = $entry['tag'];
239
		}
240

  
241
		$this->assertTrue(count($tags) > 0, 'The tags do not exist.');
223 242
		$this->assertTrue(in_array('UnitTestTag%tag1', $tags), 'Tag UnitTestTag%tag1 does not exist.');
224 243
		$this->assertTrue(in_array('UnitTestTag%tag2', $tags), 'Tag UnitTestTag%tag2 does not exist.');
225 244
	}
......
336 355
		$this->assertTrue(is_array($entriesFound) && count($entriesFound) > 0, 'The cache entry does not exist.');
337 356

  
338 357
		sleep(2);
358
		$GLOBALS['EXEC_TIME'] += 2;
339 359
		$this->backend->collectGarbage();
340 360

  
341 361
		$entriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
......
377 397
		$this->assertTrue(is_array($entriesFound) && count($entriesFound) > 0, 'The cache entries do not exist.');
378 398

  
379 399
		sleep(2);
400
		$GLOBALS['EXEC_TIME'] += 2;
380 401
		$this->backend->collectGarbage();
381 402

  
382 403
		$entriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
......
495 516
		$this->backend->set($expiredEntryIdentifier, $expiredData, array(), 1);
496 517

  
497 518
		sleep(2);
519
		$GLOBALS['EXEC_TIME'] += 2;
498 520

  
499 521
		$this->assertFalse($this->backend->has($expiredEntryIdentifier), 'has() did not return FALSE.');
500 522
	}
......
522 544
		$this->backend->set($expiredEntryIdentifier, $expiredData, array(), 1);
523 545

  
524 546
		sleep(2);
547
		$GLOBALS['EXEC_TIME'] += 2;
525 548

  
526 549
		$this->assertEquals($data, $this->backend->get($entryIdentifier), 'The original and the retrieved data don\'t match.');
527 550
		$this->assertFalse($this->backend->get($expiredEntryIdentifier), 'The expired entry could be loaded.');
......
543 566
		$this->backend->set('BackendDbTest', 'some data', array('UnitTestTag%special'), 1);
544 567

  
545 568
		sleep(2);
569
		$GLOBALS['EXEC_TIME'] += 2;
570
			// Not required, but used to update the pre-calculated queries:
571
		$this->backend->setTagsTable($this->testingTagsTable);
546 572

  
547 573
		$this->assertEquals(array(), $this->backend->findIdentifiersByTag('UnitTestTag%special'));
548 574
	}
......
579 605

  
580 606

  
581 607
	/**
582
	 * @test
583 608
	 * @author Ingo Renner <ingo@typo3.org>
584 609
	 */
585 610
	public function tearDown() {
586 611
		$GLOBALS['TYPO3_DB']->sql_query(
587 612
			'DROP TABLE ' . $this->testingCacheTable . ';'
588 613
		);
614

  
615
		$GLOBALS['TYPO3_DB']->sql_query(
616
			'DROP TABLE ' . $this->testingTagsTable . ';'
617
		);
589 618
	}
590 619

  
591 620
}
t3lib/config_default.php (Arbeitskopie)
123 123
				'cache_hash' => array(
124 124
					'backend' => 't3lib_cache_backend_DbBackend',
125 125
					'options' => array(
126
						'cacheTable' => 'cachingframework_cache_hash'
126
						'cacheTable' => 'cachingframework_cache_hash',
127
						'tagsTable' => 'cachingframework_cache_hash_tags',
127 128
					)
128 129
				),
129 130
				'cache_pages' => array(
130 131
					'backend' => 't3lib_cache_backend_DbBackend',
131 132
					'options' => array(
132
						'cacheTable' => 'cachingframework_cache_pages'
133
						'cacheTable' => 'cachingframework_cache_pages',
134
						'tagsTable' => 'cachingframework_cache_pages_tags',
133 135
					)
134 136
				),
135 137
				'cache_pagesection' => array(
136 138
					'backend' => 't3lib_cache_backend_DbBackend',
137 139
					'options' => array(
138
						'cacheTable' => 'cachingframework_cache_pagesection'
140
						'cacheTable' => 'cachingframework_cache_pagesection',
141
						'tagsTable' => 'cachingframework_cache_pagesection_tags',
139 142
					)
140 143
				)
141 144
				/*
t3lib/stddb/tables.sql (Arbeitskopie)
138 138
#
139 139
CREATE TABLE cachingframework_cache_hash (
140 140
  id int(11) unsigned NOT NULL auto_increment,
141
  identifier varchar(250) DEFAULT '' NOT NULL,
141
  identifier varchar(128) DEFAULT '' NOT NULL,
142 142
  crdate int(11) unsigned DEFAULT '0' NOT NULL,
143 143
  content mediumtext,
144
  tags mediumtext,
145 144
  lifetime int(11) unsigned DEFAULT '0' NOT NULL,
146 145
  PRIMARY KEY (id),
147 146
  KEY cache_id (identifier)
148 147
) ENGINE=InnoDB;
149 148

  
149

  
150 150
#
151
# Table structure for table 'cachingframework_cache_hash_tags'
152
#
153
CREATE TABLE cachingframework_cache_hash_tags (
154
  id int(11) unsigned NOT NULL auto_increment,
155
  identifier varchar(128) DEFAULT '' NOT NULL,
156
  tag varchar(128) DEFAULT '' NOT NULL,
157
  PRIMARY KEY (id),
158
  KEY cache_id (identifier),
159
  KEY cache_tag (tag)
160
) ENGINE=InnoDB;
161

  
162

  
163
#
151 164
# Table structure for table 'cache_imagesizes'
152 165
#
153 166
CREATE TABLE cache_imagesizes (
t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php (Arbeitskopie)
33 33
class t3lib_cache_backend_DbBackend extends t3lib_cache_backend_AbstractBackend {
34 34

  
35 35
	protected $cacheTable;
36
	protected $tagsTable;
36 37

  
38
	protected $identifierField;
39
	protected $creationField;
40
	protected $lifetimeField;
41
	protected $notExpiredStatement;
42
	protected $tableList;
43
	protected $tableJoin;
44

  
37 45
	/**
46
	 * Constructs this backend
47
	 *
48
	 * @param mixed Configuration options - depends on the actual backend
49
	 */
50
	public function __construct(array $options = array()) {
51
		parent::__construct($options);
52

  
53
		if (!$this->cacheTable) {
54
			throw new t3lib_cache_Exception(
55
				'No table to write data to has been set using the setting "cacheTable".',
56
				1253534136
57
			);
58
		}
59

  
60
		if (!$this->tagsTable) {
61
			throw new t3lib_cache_Exception(
62
				'No table to write tags to has been set using the setting "tagsTable".',
63
				1253534137
64
			);
65
		}
66

  
67
		$this->initializeCommonReferences();
68
	}
69

  
70
	/**
71
	 * Initializes common references used in this backend.
72
	 *
73
	 * @return	void
74
	 */
75
	protected function initializeCommonReferences() {
76
		$this->identifierField = $this->cacheTable . '.identifier';
77
		$this->creationField = $this->cacheTable . '.crdate';
78
		$this->lifetimeField = $this->cacheTable . '.lifetime';
79
		$this->tableList = $this->cacheTable . ', ' . $this->tagsTable;
80
		$this->tableJoin = $this->identifierField . ' = ' . $this->tagsTable . '.identifier';
81
		$this->notExpiredStatement = '(' . $this->creationField . ' + ' . $this->lifetimeField .
82
			' >= ' . $GLOBALS['EXEC_TIME'] . ' OR ' . $this->lifetimeField . ' = 0)';
83
	}
84

  
85
	/**
38 86
	 * Saves data in a cache file.
39 87
	 *
40 88
	 * @param string An identifier for this specific cache entry
......
73 121
				'identifier' => $entryIdentifier,
74 122
				'crdate'     => $GLOBALS['EXEC_TIME'],
75 123
				'content'    => $data,
76
				'tags'       => implode(',', $tags),
77 124
				'lifetime'   => $lifetime
78 125
			)
79 126
		);
127

  
128
		foreach ($tags as $tag) {
129
			$GLOBALS['TYPO3_DB']->exec_INSERTquery(
130
				$this->tagsTable,
131
				array(
132
					'identifier' => $entryIdentifier,
133
					'tag'        => $tag,
134
				)
135
			);
136
		}
80 137
	}
81 138

  
82 139
	/**
......
143 200
			'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->cacheTable)
144 201
		);
145 202

  
203
		$GLOBALS['TYPO3_DB']->exec_DELETEquery(
204
			$this->tagsTable,
205
			'identifier = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($entryIdentifier, $this->tagsTable)
206
		);
207

  
146 208
		if($GLOBALS['TYPO3_DB']->sql_affected_rows($res) == 1) {
147 209
			$entryRemoved = true;
148 210
		}
......
161 223
		$cacheEntryIdentifiers = array();
162 224

  
163 225
		$cacheEntryIdentifierRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
164
			'identifier',
165
			$this->cacheTable,
166
			$this->getListQueryForTag($tag) . ' AND (crdate + lifetime >= ' . $GLOBALS['EXEC_TIME'] . ' OR lifetime = 0)'
226
			$this->identifierField,
227
			$this->tableList,
228
			$this->getQueryForTag($tag) .
229
				' AND ' . $this->tableJoin .
230
				' AND ' . $this->notExpiredStatement,
231
			$this->identifierField
167 232
		);
168 233

  
169 234
		foreach ($cacheEntryIdentifierRows as $cacheEntryIdentifierRow) {
......
186 251
		$whereClause  = array();
187 252

  
188 253
		foreach ($tags as $tag) {
189
			$whereClause[] = $this->getListQueryForTag($tag);
254
			$whereClause[] = $this->getQueryForTag($tag);
190 255
		}
191
		$whereClause[] = '(crdate + lifetime >= ' . $GLOBALS['EXEC_TIME'] . ' OR lifetime = 0)';
192 256

  
257
		$whereClause[] = $this->tableJoin;
258
		$whereClause[] = $this->notExpiredStatement;
259

  
193 260
		$cacheEntryIdentifierRows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
194
			'identifier',
195
			$this->cacheTable,
196
			implode(' AND ', $whereClause)
261
			$this->identifierField,
262
			$this->tableList,
263
			implode(' AND ', $whereClause),
264
			$this->identifierField
197 265
		);
198 266

  
199 267
		foreach ($cacheEntryIdentifierRows as $cacheEntryIdentifierRow) {
......
211 279
	 */
212 280
	public function flush() {
213 281
		$GLOBALS['TYPO3_DB']->sql_query('TRUNCATE ' . $this->cacheTable);
282
		$GLOBALS['TYPO3_DB']->sql_query('TRUNCATE ' . $this->tagsTable);
214 283
	}
215 284

  
216 285
	/**
......
220 289
	 * @return void
221 290
	 */
222 291
	public function flushByTag($tag) {
223
		$GLOBALS['TYPO3_DB']->exec_DELETEquery(
224
			$this->cacheTable,
225
			$this->getListQueryForTag($tag)
292
		$GLOBALS['TYPO3_DB']->exec_DELETEmultipleTablesQuery(
293
			$this->tableList,
294
			$this->tableList,
295
			$this->tableJoin .
296
				' AND ' . $this->getQueryForTag($tag)
226 297
		);
227 298
	}
228 299

  
......
233 304
	 * @return void
234 305
	 */
235 306
	public function flushByTags(array $tags) {
236
		$listQueryConditions = array();
237
		foreach ($tags as $tag) {
238
			$listQueryConditions[$tag] = $this->getListQueryForTag($tag);
307
		if (count($tags)) {
308
			$listQueryConditions = array();
309
			foreach ($tags as $tag) {
310
				$listQueryConditions[$tag] = $this->getQueryForTag($tag);
311
			}
312
	
313
			$GLOBALS['TYPO3_DB']->exec_DELETEmultipleTablesQuery(
314
				$this->tableList,
315
				$this->tableList,
316
				$this->tableJoin .
317
					' AND (' . implode(' OR ', $listQueryConditions) . ')'
318
			);
239 319
		}
240

  
241
		$listQuery = implode(' OR ', $listQueryConditions);
242
		$GLOBALS['TYPO3_DB']->exec_DELETEquery(
243
			$this->cacheTable,
244
			$listQuery
245
		);
246 320
	}
247 321

  
248 322
	/**
......
252 326
	 * @author Ingo Renner <ingo@typo3.org>
253 327
	 */
254 328
	public function collectGarbage() {
329
		$GLOBALS['TYPO3_DB']->exec_DELETEmultipleTablesQuery(
330
			$this->tableList,
331
			$this->tableList,
332
			$this->tableJoin .
333
				' AND ' . $this->cacheTable . '.crdate + ' . $this->cacheTable . '.lifetime < ' . $GLOBALS['EXEC_TIME'] .
334
				' AND ' . $this->cacheTable . '.lifetime > 0'
335
		);
336

  
255 337
		$GLOBALS['TYPO3_DB']->exec_DELETEquery(
256 338
			$this->cacheTable,
257 339
			'crdate + lifetime < ' . $GLOBALS['EXEC_TIME'] . ' AND lifetime > 0'
......
300 382
		}
301 383
*/
302 384
		$this->cacheTable = $cacheTable;
385
		$this->initializeCommonReferences();
303 386
	}
304 387

  
305 388
	/**
......
313 396
	}
314 397

  
315 398
	/**
399
	 * Sets the table where cache tags are stored.
400
	 *
401
	 * @param	string		$tagsTabls: Name of the table
402
	 * @return	void
403
	 */
404
	public function setTagsTable($tagsTable) {
405
		$this->tagsTable = $tagsTable;
406
		$this->initializeCommonReferences();
407
	}
408

  
409
	/**
410
	 * Gets the table where cache tags are stored.
411
	 *
412
	 * @return	string		Name of the table storing tags
413
	 */
414
	public function getTagsTable() {
415
		return $this->tagsTable;
416
	}
417

  
418
	/**
316 419
	 * Gets the query to be used for selecting entries by a tag. The asterisk ("*")
317 420
	 * is allowed as a wildcard at the beginning and the end of a tag.
318 421
	 *
......
320 423
	 * @return string the query to be used for selecting entries
321 424
	 * @author Oliver Hader <oliver@typo3.org>
322 425
	 */
323
	protected function getListQueryForTag($tag) {
324
		return str_replace('*', '%', $GLOBALS['TYPO3_DB']->listQuery('tags', $tag, $this->cacheTable));
426
	protected function getQueryForTag($tag) {
427
		if (strpos($tag, '*') === false) {
428
			$query = $this->tagsTable . '.tag = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($tag, $this->tagsTable);
429
		} else {
430
			$patternForLike = $GLOBALS['TYPO3_DB']->escapeStrForLike(
431
				$GLOBALS['TYPO3_DB']->quoteStr($tag, $this->tagsTable),
432
				$this->tagsTable
433
			);
434
			$query = $this->tagsTable . '.tag LIKE \'' . $patternForLike . '\'';
435
		}
436

  
437
		return $query;
325 438
	}
326 439
}
327 440

  
t3lib/class.t3lib_db.php (Arbeitskopie)
216 216
	}
217 217

  
218 218
	/**
219
	 * Creates and executes a DELETE SQL-statement for multiple tables.
220
	 *
221
	 * @param	string		$tablesToDeleteFrom: Name of the tables to delete from
222
	 * @param	string		$tablesReference: Name of the tables references join the results
223
	 * @param	string		$where: WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
224
	 * @return	pointer		MySQL result pointer
225
	 */
226
	public function exec_DELETEmultipleTablesQuery($tablesToDeleteFrom, $tablesReference, $where) {
227
		$res = mysql_query($this->DELETEmultipleTablesQuery($tablesToDeleteFrom, $tablesReference, $where), $this->link);
228
		if ($this->debugOutput) {
229
			$this->debug('exec_DELETEquery');
230
		}
231
		return $res;
232
	}
233

  
234
	/**
219 235
	 * Creates and executes a SELECT SQL-statement
220 236
	 * Using this function specifically allow us to handle the LIMIT feature independently of DB.
221 237
	 * Usage count/core: 340
......
466 482
	}
467 483

  
468 484
	/**
485
	 * Creates a DELETE SQL-statement for multiple tables
486
	 * Usage count/core: 3
487
	 *
488
	 * @param	string		See exec_DELETEmultipleTablesQuery()
489
	 * @param	string		See exec_DELETEmultipleTablesQuery()
490
	 * @param	string		See exec_DELETEmultipleTablesQuery()
491
	 * @return	string		Full SQL query for DELETE from multiple tables
492
	 */
493
	public function DELETEmultipleTablesQuery($tablesToDeleteFrom, $tablesReference, $where) {
494
		if (is_string($where)) {
495
				// Table and fieldnames should be "SQL-injection-safe" when supplied to this function
496
			$query = 'DELETE ' . $tablesToDeleteFrom . ' FROM ' . $tablesReference .
497
				(strlen($where) > 0 ? ' WHERE ' . $where : '');
498

  
499
			if ($this->debugOutput || $this->store_lastBuiltQuery) {
500
				$this->debug_lastBuiltQuery = $query;
501
			}
502

  
503
			return $query;
504
		} else {
505
			die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for DELETE query was not a string in $this->DELETEmultipleTablesQuery() !');
506
		}
507
	}
508

  
509
	/**
469 510
	 * Creates a SELECT SQL-statement
470 511
	 * Usage count/core: 11
471 512
	 *
typo3/sysext/cms/ext_tables.sql (Arbeitskopie)
41 41
#
42 42
CREATE TABLE cachingframework_cache_pages (
43 43
  id int(11) unsigned NOT NULL auto_increment,
44
  identifier varchar(250) DEFAULT '' NOT NULL,
44
  identifier varchar(128) DEFAULT '' NOT NULL,
45 45
  crdate int(11) unsigned DEFAULT '0' NOT NULL,
46 46
  content mediumtext,
47
  tags mediumtext,
48 47
  lifetime int(11) unsigned DEFAULT '0' NOT NULL,
49 48
  PRIMARY KEY (id),
50 49
  KEY cache_id (identifier)
......
52 51

  
53 52

  
54 53
#
54
# Table structure for table 'cachingframework_cache_pages_tags'
55
#
56
CREATE TABLE cachingframework_cache_pages_tags (
57
  id int(11) unsigned NOT NULL auto_increment,
58
  identifier varchar(128) DEFAULT '' NOT NULL,
59
  tag varchar(128) DEFAULT '' NOT NULL,
60
  PRIMARY KEY (id),
61
  KEY cache_id (identifier),
62
  KEY cache_tag (tag)
63
) ENGINE=InnoDB;
64

  
65

  
66
#
55 67
# Table structure for table 'cachingframework_cache_pagesection'
56 68
#
57 69
CREATE TABLE cachingframework_cache_pagesection (
58 70
  id int(11) unsigned NOT NULL auto_increment,
59
  identifier varchar(250) DEFAULT '' NOT NULL,
71
  identifier varchar(128) DEFAULT '' NOT NULL,
60 72
  crdate int(11) unsigned DEFAULT '0' NOT NULL,
61 73
  content mediumtext,
62
  tags mediumtext,
63 74
  lifetime int(11) unsigned DEFAULT '0' NOT NULL,
64 75
  PRIMARY KEY (id),
65 76
  KEY cache_id (identifier)
......
67 78

  
68 79

  
69 80
#
81
# Table structure for table 'cachingframework_cache_pagesection_tags'
82
#
83
CREATE TABLE cachingframework_cache_pagesection_tags (
84
  id int(11) unsigned NOT NULL auto_increment,
85
  identifier varchar(128) DEFAULT '' NOT NULL,
86
  tag varchar(128) DEFAULT '' NOT NULL,
87
  PRIMARY KEY (id),
88
  KEY cache_id (identifier),
89
  KEY cache_tag (tag)
90
) ENGINE=InnoDB;
91

  
92

  
93
#
70 94
# Table structure for table 'cache_typo3temp_log'
71 95
#
72 96
CREATE TABLE cache_typo3temp_log (