提交 18808fa8 authored 作者: noelgrandin's avatar noelgrandin

Add a DISK_SPACE_USED system function. Fixes issue 270.

上级 cf7ee9c5
...@@ -3573,6 +3573,16 @@ This function is provided for Oracle compatibility (see there for details). ...@@ -3573,6 +3573,16 @@ This function is provided for Oracle compatibility (see there for details).
CALL DECODE(RAND()>0.5, 0, 'Red', 1, 'Black'); CALL DECODE(RAND()>0.5, 0, 'Red', 1, 'Black');
" "
"Functions (System)","DISK_SPACE_USED","
DISK_SPACE_USED(tablename)
","
Returns the approximate amount of space used by the table specified.
Does not currently take into account indexes or LOB's.
This function may be expensive since it has to load every page in the table.
","
CALL DISK_SPACE_USED('my_table');
"
"Functions (System)","FILE_READ"," "Functions (System)","FILE_READ","
FILE_READ(fileNameString [,encodingString]) FILE_READ(fileNameString [,encodingString])
"," ","
......
...@@ -36,6 +36,7 @@ Change Log ...@@ -36,6 +36,7 @@ Change Log
</ul><li>Support ALTER TABLE ADD ... AFTER. Patch from Andrew Gaul (argaul at gmail.com). Fixes issue 401. </ul><li>Support ALTER TABLE ADD ... AFTER. Patch from Andrew Gaul (argaul at gmail.com). Fixes issue 401.
</ul><li>support "SELECT version()". Patch from Andrew Gaul. Fixes issue 406. </ul><li>support "SELECT version()". Patch from Andrew Gaul. Fixes issue 406.
</ul><li>Improved OSGi support. H2 now registers itself as a DataSourceFactory service. Fixes issue 365. </ul><li>Improved OSGi support. H2 now registers itself as a DataSourceFactory service. Fixes issue 365.
</ul><li>Add a DISK_SPACE_USED system function. Fixes issue 270.
</li></ul> </li></ul>
<h2>Version 1.3.170 (2012-11-30)</h2> <h2>Version 1.3.170 (2012-11-30)</h2>
......
...@@ -5379,4 +5379,16 @@ public class Parser { ...@@ -5379,4 +5379,16 @@ public class Parser {
return readExpression(); return readExpression();
} }
/**
* Parse a SQL code snippet that represents a table name.
*
* @param sql the code snippet
* @return the table object
*/
public Table parseTableName(String sql) {
parameters = New.arrayList();
initialize(sql);
read();
return readTableOrView();
}
} }
...@@ -40,6 +40,7 @@ import org.h2.store.fs.FileUtils; ...@@ -40,6 +40,7 @@ import org.h2.store.fs.FileUtils;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.LinkSchema; import org.h2.table.LinkSchema;
import org.h2.table.Table;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.tools.CompressTool; import org.h2.tools.CompressTool;
import org.h2.tools.Csv; import org.h2.tools.Csv;
...@@ -92,7 +93,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -92,7 +93,7 @@ public class Function extends Expression implements FunctionCall {
ISO_YEAR = 123, ISO_WEEK = 124, ISO_DAY_OF_WEEK = 125; ISO_YEAR = 123, ISO_WEEK = 124, ISO_DAY_OF_WEEK = 125;
public static final int DATABASE = 150, USER = 151, CURRENT_USER = 152, IDENTITY = 153, SCOPE_IDENTITY = 154, public static final int DATABASE = 150, USER = 151, CURRENT_USER = 152, IDENTITY = 153, SCOPE_IDENTITY = 154,
AUTOCOMMIT = 155, READONLY = 156, DATABASE_PATH = 157, LOCK_TIMEOUT = 158; AUTOCOMMIT = 155, READONLY = 156, DATABASE_PATH = 157, LOCK_TIMEOUT = 158, DISK_SPACE_USED = 159;
public static final int IFNULL = 200, CASEWHEN = 201, CONVERT = 202, CAST = 203, COALESCE = 204, NULLIF = 205, public static final int IFNULL = 200, CASEWHEN = 201, CONVERT = 202, CAST = 203, COALESCE = 204, NULLIF = 205,
CASE = 206, NEXTVAL = 207, CURRVAL = 208, ARRAY_GET = 209, CSVREAD = 210, CSVWRITE = 211, CASE = 206, NEXTVAL = 207, CURRVAL = 208, ARRAY_GET = 209, CSVREAD = 210, CSVWRITE = 211,
...@@ -346,6 +347,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -346,6 +347,7 @@ public class Function extends Expression implements FunctionCall {
addFunctionNotDeterministic("TRANSACTION_ID", TRANSACTION_ID, 0, Value.STRING); addFunctionNotDeterministic("TRANSACTION_ID", TRANSACTION_ID, 0, Value.STRING);
addFunctionWithNull("DECODE", DECODE, VAR_ARGS, Value.NULL); addFunctionWithNull("DECODE", DECODE, VAR_ARGS, Value.NULL);
addFunction("VERSION", VERSION, 0, Value.STRING); addFunction("VERSION", VERSION, 0, Value.STRING);
addFunctionNotDeterministic("DISK_SPACE_USED", DISK_SPACE_USED, 1, Value.LONG);
// TableFunction // TableFunction
addFunctionWithNull("TABLE", TABLE, VAR_ARGS, Value.RESULT_SET); addFunctionWithNull("TABLE", TABLE, VAR_ARGS, Value.RESULT_SET);
...@@ -760,6 +762,9 @@ public class Function extends Expression implements FunctionCall { ...@@ -760,6 +762,9 @@ public class Function extends Expression implements FunctionCall {
case LOCK_TIMEOUT: case LOCK_TIMEOUT:
result = ValueInt.get(session.getLockTimeout()); result = ValueInt.get(session.getLockTimeout());
break; break;
case DISK_SPACE_USED:
result = ValueLong.get(getDiskSpaceUsed(session, v0));
break;
case CAST: case CAST:
case CONVERT: { case CONVERT: {
v0 = v0.convertTo(dataType); v0 = v0.convertTo(dataType);
...@@ -942,6 +947,13 @@ public class Function extends Expression implements FunctionCall { ...@@ -942,6 +947,13 @@ public class Function extends Expression implements FunctionCall {
return false; return false;
} }
private static long getDiskSpaceUsed(Session session, Value v0) {
Parser p = new Parser(session);
String sql = v0.getString();
Table table = p.parseTableName(sql);
return table.getDiskSpaceUsed();
}
private static Value getNullOrValue(Session session, Expression[] args, Value[] values, int i) { private static Value getNullOrValue(Session session, Expression[] args, Value[] values, int i) {
if (i >= args.length) { if (i >= args.length) {
return null; return null;
......
...@@ -90,6 +90,10 @@ public class FunctionIndex extends BaseIndex { ...@@ -90,6 +90,10 @@ public class FunctionIndex extends BaseIndex {
return functionTable.getRowCountApproximation(); return functionTable.getRowCountApproximation();
} }
public long getDiskSpaceUsed() {
return 0;
}
public String getPlanSQL() { public String getPlanSQL() {
return "function"; return "function";
} }
......
...@@ -81,6 +81,10 @@ public class HashIndex extends BaseIndex { ...@@ -81,6 +81,10 @@ public class HashIndex extends BaseIndex {
return rows.size(); return rows.size();
} }
public long getDiskSpaceUsed() {
return 0;
}
public void close(Session session) { public void close(Session session) {
// nothing to do // nothing to do
} }
......
...@@ -156,6 +156,11 @@ public interface Index extends SchemaObject { ...@@ -156,6 +156,11 @@ public interface Index extends SchemaObject {
*/ */
long getRowCountApproximation(); long getRowCountApproximation();
/**
* @return the estimated number of bytes of disk space used by this page and all child pages.
*/
long getDiskSpaceUsed();
/** /**
* Compare two rows. * Compare two rows.
* *
......
...@@ -246,4 +246,7 @@ public class LinkedIndex extends BaseIndex { ...@@ -246,4 +246,7 @@ public class LinkedIndex extends BaseIndex {
return rowCount; return rowCount;
} }
public long getDiskSpaceUsed() {
return 0;
}
} }
...@@ -97,6 +97,10 @@ public class MetaIndex extends BaseIndex { ...@@ -97,6 +97,10 @@ public class MetaIndex extends BaseIndex {
return MetaTable.ROW_COUNT_APPROXIMATION; return MetaTable.ROW_COUNT_APPROXIMATION;
} }
public long getDiskSpaceUsed() {
return meta.getDiskSpaceUsed();
}
public String getPlanSQL() { public String getPlanSQL() {
return "meta"; return "meta";
} }
......
...@@ -302,6 +302,10 @@ public class MultiVersionIndex implements Index { ...@@ -302,6 +302,10 @@ public class MultiVersionIndex implements Index {
return base.getRowCountApproximation(); return base.getRowCountApproximation();
} }
public long getDiskSpaceUsed() {
return base.getDiskSpaceUsed();
}
public Index getBaseIndex() { public Index getBaseIndex() {
return base; return base;
} }
......
...@@ -300,6 +300,10 @@ public class PageBtreeIndex extends PageIndex { ...@@ -300,6 +300,10 @@ public class PageBtreeIndex extends PageIndex {
return tableData.getRowCountApproximation(); return tableData.getRowCountApproximation();
} }
public long getDiskSpaceUsed() {
return tableData.getDiskSpaceUsed();
}
public long getRowCount(Session session) { public long getRowCount(Session session) {
return rowCount; return rowCount;
} }
......
...@@ -88,6 +88,11 @@ abstract class PageData extends Page { ...@@ -88,6 +88,11 @@ abstract class PageData extends Page {
*/ */
abstract void setRowCountStored(int rowCount); abstract void setRowCountStored(int rowCount);
/**
* @return the estimated number of bytes of disk space used by this page and all child pages.
*/
abstract long getDiskSpaceUsed();
/** /**
* Find an entry by key. * Find an entry by key.
* *
...@@ -229,7 +234,7 @@ abstract class PageData extends Page { ...@@ -229,7 +234,7 @@ abstract class PageData extends Page {
// to how much memory a row needs on average // to how much memory a row needs on average
return memoryEstimated; return memoryEstimated;
} }
int getParentPageId() { int getParentPageId() {
return parentPageId; return parentPageId;
} }
......
...@@ -427,6 +427,11 @@ public class PageDataIndex extends PageIndex { ...@@ -427,6 +427,11 @@ public class PageDataIndex extends PageIndex {
return rowCount; return rowCount;
} }
public long getDiskSpaceUsed() {
PageData root = getPage(rootPageId, 0);
return root.getDiskSpaceUsed();
}
public String getCreateSQL() { public String getCreateSQL() {
return null; return null;
} }
......
...@@ -451,6 +451,10 @@ public class PageDataLeaf extends PageData { ...@@ -451,6 +451,10 @@ public class PageDataLeaf extends PageData {
// ignore // ignore
} }
long getDiskSpaceUsed() {
return index.getPageStore().getPageSize();
}
public void write() { public void write() {
writeData(); writeData();
index.getPageStore().writePage(getPos(), data); index.getPageStore().writePage(getPos(), data);
......
...@@ -277,7 +277,7 @@ public class PageDataNode extends PageData { ...@@ -277,7 +277,7 @@ public class PageDataNode extends PageData {
int child = childPageIds[i]; int child = childPageIds[i];
PageData page = index.getPage(child, getPos()); PageData page = index.getPage(child, getPos());
if (getPos() == page.getPos()) { if (getPos() == page.getPos()) {
throw DbException.throwInternalError("Page it its own child: " + getPos()); throw DbException.throwInternalError("Page is its own child: " + getPos());
} }
count += page.getRowCount(); count += page.getRowCount();
index.getDatabase().setProgress(DatabaseEventListener.STATE_SCAN_FILE, index.getDatabase().setProgress(DatabaseEventListener.STATE_SCAN_FILE,
...@@ -288,6 +288,21 @@ public class PageDataNode extends PageData { ...@@ -288,6 +288,21 @@ public class PageDataNode extends PageData {
return rowCount; return rowCount;
} }
long getDiskSpaceUsed() {
long count = 0;
for (int i = 0; i < entryCount + 1; i++) {
int child = childPageIds[i];
PageData page = index.getPage(child, getPos());
if (getPos() == page.getPos()) {
throw DbException.throwInternalError("Page is its own child: " + getPos());
}
count += page.getDiskSpaceUsed();
index.getDatabase().setProgress(DatabaseEventListener.STATE_SCAN_FILE,
index.getTable() + "." + index.getName(), (int) (count>>16), Integer.MAX_VALUE);
}
return count;
}
void setRowCountStored(int rowCount) { void setRowCountStored(int rowCount) {
this.rowCount = rowCount; this.rowCount = rowCount;
if (rowCountStored != rowCount) { if (rowCountStored != rowCount) {
......
...@@ -117,6 +117,10 @@ public class PageDelegateIndex extends PageIndex { ...@@ -117,6 +117,10 @@ public class PageDelegateIndex extends PageIndex {
return mainIndex.getRowCountApproximation(); return mainIndex.getRowCountApproximation();
} }
public long getDiskSpaceUsed() {
return mainIndex.getDiskSpaceUsed();
}
public void writeRowCount() { public void writeRowCount() {
// ignore // ignore
} }
......
...@@ -95,4 +95,7 @@ public class RangeIndex extends BaseIndex { ...@@ -95,4 +95,7 @@ public class RangeIndex extends BaseIndex {
return rangeTable.getRowCountApproximation(); return rangeTable.getRowCountApproximation();
} }
public long getDiskSpaceUsed() {
return 0;
}
} }
...@@ -232,6 +232,10 @@ public class ScanIndex extends BaseIndex { ...@@ -232,6 +232,10 @@ public class ScanIndex extends BaseIndex {
return rowCount; return rowCount;
} }
public long getDiskSpaceUsed() {
return 0;
}
public String getPlanSQL() { public String getPlanSQL() {
return table.getSQL() + ".tableScan"; return table.getSQL() + ".tableScan";
} }
......
...@@ -383,4 +383,8 @@ public class TreeIndex extends BaseIndex { ...@@ -383,4 +383,8 @@ public class TreeIndex extends BaseIndex {
return rowCount; return rowCount;
} }
public long getDiskSpaceUsed() {
return 0;
}
} }
...@@ -375,6 +375,10 @@ public class ViewIndex extends BaseIndex { ...@@ -375,6 +375,10 @@ public class ViewIndex extends BaseIndex {
return 0; return 0;
} }
public long getDiskSpaceUsed() {
return 0;
}
public boolean isRecursive() { public boolean isRecursive() {
return recursive; return recursive;
} }
......
...@@ -118,4 +118,8 @@ public class MVDelegateIndex extends BaseIndex { ...@@ -118,4 +118,8 @@ public class MVDelegateIndex extends BaseIndex {
return mainIndex.getRowCountApproximation(); return mainIndex.getRowCountApproximation();
} }
public long getDiskSpaceUsed() {
return 0;
}
} }
...@@ -187,6 +187,10 @@ public class MVPrimaryIndex extends BaseIndex { ...@@ -187,6 +187,10 @@ public class MVPrimaryIndex extends BaseIndex {
return map.getSize(); return map.getSize();
} }
public long getDiskSpaceUsed() {
return 0; // TODO
}
@Override @Override
public void checkRename() { public void checkRename() {
// ok // ok
......
...@@ -150,6 +150,10 @@ public class MVSecondaryIndex extends BaseIndex { ...@@ -150,6 +150,10 @@ public class MVSecondaryIndex extends BaseIndex {
return map.getSize(); return map.getSize();
} }
public long getDiskSpaceUsed() {
return 0; // TODO
}
@Override @Override
public void checkRename() { public void checkRename() {
// ok // ok
......
...@@ -418,6 +418,10 @@ public class MVTable extends TableBase { ...@@ -418,6 +418,10 @@ public class MVTable extends TableBase {
return primaryIndex.getRowCountApproximation(); return primaryIndex.getRowCountApproximation();
} }
public long getDiskSpaceUsed() {
return primaryIndex.getDiskSpaceUsed();
}
@Override @Override
public void checkRename() { public void checkRename() {
// ok // ok
......
...@@ -216,6 +216,10 @@ public class FunctionTable extends Table { ...@@ -216,6 +216,10 @@ public class FunctionTable extends Table {
public long getRowCountApproximation() { public long getRowCountApproximation() {
return rowCount; return rowCount;
} }
public long getDiskSpaceUsed() {
return 0;
}
public boolean isDeterministic() { public boolean isDeterministic() {
return function.isDeterministic(); return function.isDeterministic();
......
...@@ -1801,6 +1801,10 @@ public class MetaTable extends Table { ...@@ -1801,6 +1801,10 @@ public class MetaTable extends Table {
return ROW_COUNT_APPROXIMATION; return ROW_COUNT_APPROXIMATION;
} }
public long getDiskSpaceUsed() {
return 0;
}
public boolean isDeterministic() { public boolean isDeterministic() {
return true; return true;
} }
......
...@@ -167,6 +167,10 @@ public class RangeTable extends Table { ...@@ -167,6 +167,10 @@ public class RangeTable extends Table {
return 100; return 100;
} }
public long getDiskSpaceUsed() {
return 0;
}
public boolean isDeterministic() { public boolean isDeterministic() {
return true; return true;
} }
......
...@@ -724,6 +724,11 @@ public class RegularTable extends TableBase { ...@@ -724,6 +724,11 @@ public class RegularTable extends TableBase {
public long getRowCountApproximation() { public long getRowCountApproximation() {
return scanIndex.getRowCountApproximation(); return scanIndex.getRowCountApproximation();
} }
@Override
public long getDiskSpaceUsed() {
return scanIndex.getDiskSpaceUsed();
}
public void setCompareMode(CompareMode compareMode) { public void setCompareMode(CompareMode compareMode) {
this.compareMode = compareMode; this.compareMode = compareMode;
......
...@@ -293,6 +293,8 @@ public abstract class Table extends SchemaObjectBase { ...@@ -293,6 +293,8 @@ public abstract class Table extends SchemaObjectBase {
*/ */
public abstract long getRowCountApproximation(); public abstract long getRowCountApproximation();
public abstract long getDiskSpaceUsed();
/** /**
* Get the row id column if this table has one. * Get the row id column if this table has one.
* *
......
...@@ -598,6 +598,10 @@ public class TableLink extends Table { ...@@ -598,6 +598,10 @@ public class TableLink extends Table {
return ROW_COUNT_APPROXIMATION; return ROW_COUNT_APPROXIMATION;
} }
public long getDiskSpaceUsed() {
return 0;
}
/** /**
* Add this prepared statement to the list of cached statements. * Add this prepared statement to the list of cached statements.
* *
......
...@@ -437,6 +437,10 @@ public class TableView extends Table { ...@@ -437,6 +437,10 @@ public class TableView extends Table {
return ROW_COUNT_APPROXIMATION; return ROW_COUNT_APPROXIMATION;
} }
public long getDiskSpaceUsed() {
return 0;
}
public int getParameterOffset() { public int getParameterOffset() {
return topQuery == null ? 0 : topQuery.getParameters().size(); return topQuery == null ? 0 : topQuery.getParameters().size();
} }
......
...@@ -148,6 +148,10 @@ public class TestTableEngines extends TestBase { ...@@ -148,6 +148,10 @@ public class TestTableEngines extends TestBase {
return table.getRowCountApproximation(); return table.getRowCountApproximation();
} }
public long getDiskSpaceUsed() {
return table.getDiskSpaceUsed();
}
public long getRowCount(Session session) { public long getRowCount(Session session) {
return table.getRowCount(session); return table.getRowCount(session);
} }
...@@ -257,6 +261,10 @@ public class TestTableEngines extends TestBase { ...@@ -257,6 +261,10 @@ public class TestTableEngines extends TestBase {
return row == null ? 0 : 1; return row == null ? 0 : 1;
} }
public long getDiskSpaceUsed() {
return 0;
}
@Override @Override
public Index getScanIndex(Session session) { public Index getScanIndex(Session session) {
return scanIndex; return scanIndex;
......
...@@ -9972,3 +9972,13 @@ select * from word; ...@@ -9972,3 +9972,13 @@ select * from word;
drop table word; drop table word;
> ok > ok
create table test(id int, name varchar);
> ok
insert into test values(5, 'b'), (5, 'b'), (20, 'a');
> update count: 3
CALL DISK_SPACE_USED('test');
> DISK_SPACE_USED('test')
> -----------------------
> 2048
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论