Skip to content
This repository was archived by the owner on May 12, 2021. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
ea6aeb3
TAJO-1353: CREATE TABLE should support the nested record definition.
hyunsik Feb 21, 2015
e3ad19f
Changed the type name 'struct' to 'record'.
hyunsik Feb 21, 2015
bb39a91
Introduced TypeDesc which contains DataType and NestedSchema.
hyunsik Feb 21, 2015
a21c110
Introduced nested record to schema almostly.
hyunsik Feb 22, 2015
1c6b21d
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Feb 27, 2015
1c8d258
TAJO-1329: Improve Schema class to support nested struct support.
hyunsik Feb 27, 2015
0ef6018
Change child_fields_num to nested_field_num.
hyunsik Feb 27, 2015
458ed0e
Refactor resolver and its releated things:
hyunsik Feb 28, 2015
66693e4
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 5, 2015
a2d0741
Allow catalog stores to have duplicated names across the different le…
hyunsik Mar 5, 2015
8c000ce
Fixed unique key of derby.
hyunsik Mar 6, 2015
4ca4e0e
In progress.
hyunsik Mar 11, 2015
50076d8
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 11, 2015
38c61e1
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 11, 2015
f5fdb02
Add missed nested field support.
hyunsik Mar 11, 2015
c252111
Merge branch 'TAJO-1329' of github.com:hyunsik/tajo into TAJO-1329
hyunsik Mar 11, 2015
cc5ab77
Merge branch 'TAJO-1329' of github.com:hyunsik/tajo into TAJO-1359
hyunsik Mar 11, 2015
8b3f45e
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 12, 2015
f10f752
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 12, 2015
b271d4d
Update schema in xml files.
hyunsik Mar 12, 2015
cfa95eb
Updated catalog store driver versions.
hyunsik Mar 12, 2015
6b4e38a
Merge branch 'TAJO-1329' of github.com:hyunsik/tajo into TAJO-1359
hyunsik Mar 12, 2015
3506212
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 13, 2015
f3cf891
Fixed the bug about the duplicated names in different level.
hyunsik Mar 13, 2015
2567c32
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 13, 2015
04bb0e1
Merge branch 'TAJO-1329' of github.com:hyunsik/tajo into TAJO-1359
hyunsik Mar 13, 2015
6a6eb18
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 13, 2015
899deea
Completed complex type support.
hyunsik Mar 14, 2015
ed3b54a
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 14, 2015
d2bef28
Added twitter json example tests.
hyunsik Mar 14, 2015
5fa31c3
Fixed unit tests.
hyunsik Mar 19, 2015
22febde
Fixed resolving problem.
hyunsik Mar 19, 2015
5d6b6d1
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 19, 2015
e30b9f9
Add more comments.
hyunsik Mar 19, 2015
b92d935
Improve Scanner to produce more narrow tuples.
hyunsik Mar 20, 2015
447b4bd
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/tajo…
hyunsik Mar 21, 2015
1c2b310
Fixed findbugs warnings.
hyunsik Mar 21, 2015
b369d1c
Merge branch 'master' of github.com:apache/tajo into TAJO-1359
hyunsik May 1, 2015
558e944
Rename and bug fix.
hyunsik May 6, 2015
55783df
Merge branch 'master' of github.com:apache/tajo into TAJO-1359
hyunsik May 6, 2015
36827b3
Fixed bugs cauesd by recent changes.
hyunsik May 6, 2015
244df79
Changed a comment.
hyunsik May 6, 2015
0f73b96
Fixed some findbug warnings.
hyunsik May 6, 2015
d239a64
Merge branch 'master' of github.com:apache/tajo into TAJO-1359
hyunsik May 6, 2015
c5263f4
Fixed NPE.
hyunsik May 7, 2015
95e8596
Fixed LogicalPlanner to prohibit the projection of record type.
hyunsik May 7, 2015
b23f706
Reflected reviewer's comments.
hyunsik May 7, 2015
4ddd2eb
Fixed wrong exception bug.
hyunsik May 8, 2015
84c3a2e
Merge branch 'master' of github.com:apache/tajo into TAJO-1359
hyunsik May 8, 2015
77e1bf0
Fixed unit test failures.
hyunsik May 9, 2015
744e3ec
Add error log message to exception
hyunsik May 11, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ public static boolean isDelimited(String identifier) {
return openQuote && closeQuote;
}

/**
* True if a given name is a simple identifier, meaning is not a dot-chained name.
*
* @param columnOrTableName Column or Table name to be checked
* @return True if a given name is a simple identifier. Otherwise, it will return False.
*/
public static boolean isSimpleIdentifier(String columnOrTableName) {
return columnOrTableName.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP).length == 1;
}

public static boolean isFQColumnName(String tableName) {
return tableName.split(CatalogConstants.IDENTIFIER_DELIMITER_REGEXP).length == 3;
}
Expand Down Expand Up @@ -662,7 +672,7 @@ public static DataType getWidestType(DataType...types) {
if (types[i].getType() != Type.NULL_TYPE) {
Type candidate = TUtil.getFromNestedMap(OPERATION_CASTING_MAP, widest.getType(), types[i].getType());
if (candidate == null) {
throw new InvalidOperationException("No matched operation for those types: " + TUtil.arrayToString
throw new InvalidOperationException("No matched operation for those types: " + StringUtils.join
(types));
}
widest = newSimpleDataType(candidate);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.tajo.catalog;

import com.google.common.base.Preconditions;
import org.apache.tajo.common.TajoDataTypes.Type;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* Utility methods for nested field
*/
public class NestedPathUtil {
public static final String PATH_DELIMITER = "/";

public static final List<String> ROOT_PATH = Collections.unmodifiableList(new ArrayList<String>());

public static boolean isPath(String name) {
return name.indexOf(PATH_DELIMITER.charAt(0)) >= 0;
}

public static String makePath(String[] parts) {
return makePath(parts, 0);
}

public static String makePath(String[] parts, int startIndex) {
return makePath(parts, startIndex, parts.length);
}

/**
* Make a nested field path
*
* @param parts path parts
* @param startIndex startIndex
* @param depth Depth
* @return Path
*/
public static String makePath(String[] parts, int startIndex, int depth) {
Preconditions.checkArgument(startIndex <= (parts.length - 1));

StringBuilder sb = new StringBuilder();
for (int i = startIndex; i < depth; i++) {
sb.append(PATH_DELIMITER);
sb.append(parts[i].toString());
}

return sb.toString();
}

/**
* Lookup the actual column corresponding to a given path.
* We assume that a path starts with the slash '/' and it
* does not include the root field.
*
* @param nestedField Nested column
* @param path Path which starts with '/';
* @return Column corresponding to the path
*/
public static Column lookupPath(Column nestedField, String path) {
Preconditions.checkArgument(path.charAt(0) == PATH_DELIMITER.charAt(0),
"A nested field path must start with slash '/'.");

// We assume that path starts with '/', causing an empty string "" at 0 in the path splits.
// So, we should start the index from 1 instead of 0.
return lookupPath(nestedField, path.split(PATH_DELIMITER));
}

public static Column lookupPath(Column nestedField, String [] paths) {
// We assume that path starts with '/', causing an empty string "" at 0 in the path splits.
// So, we should start the index from 1 instead of 0.
return lookupColumnInternal(nestedField, paths, 1);
}

private static Column lookupColumnInternal(Column currentColumn, String [] paths, int depth) {
Column found = null;

if (currentColumn.getDataType().getType() == Type.RECORD) {
found = currentColumn.typeDesc.nestedRecordSchema.getColumn(paths[depth]);
}

if (found != null) {
if (found.getDataType().getType() == Type.RECORD) {
return lookupColumnInternal(found, paths, depth + 1);
} else {
return found;
}
} else {
throw new NoSuchFieldError(makePath(paths));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.tajo.common.TajoDataTypes.DataType;
import org.apache.tajo.common.TajoDataTypes.Type;
import org.apache.tajo.json.GsonObject;
import org.apache.tajo.util.StringUtils;
import org.apache.tajo.util.TUtil;

import java.util.*;
Expand Down Expand Up @@ -135,7 +136,8 @@ private void init() {
* @param qualifier The qualifier
*/
public void setQualifier(String qualifier) {
List<Column> columns = getColumns();
// only change root fields, and must keep each nested field simple name
List<Column> columns = getRootColumns();

fields.clear();
fieldsByQualifiedName.clear();
Expand Down Expand Up @@ -180,14 +182,39 @@ public int getIndex(Column column) {
* @return The column matched to a given column name.
*/
public Column getColumn(String name) {
String [] parts = name.split("\\.");
// Some of the string can includes database name and table name and column name.
// For example, it can be 'default.table1.id'.
// Therefore, spilt string array length can be 3.
if (parts.length >= 2) {
return getColumnByQName(name);

if (NestedPathUtil.isPath(name)) {

// TODO - to be refactored
if (fieldsByQualifiedName.containsKey(name)) {
Column flattenColumn = fields.get(fieldsByQualifiedName.get(name));
if (flattenColumn != null) {
return flattenColumn;
}
}

String [] paths = name.split(NestedPathUtil.PATH_DELIMITER);
Column column = getColumn(paths[0]);
if (column == null) {
return null;
}
Column actualColumn = NestedPathUtil.lookupPath(column, paths);

Column columnPath = new Column(
column.getQualifiedName() + NestedPathUtil.makePath(paths, 1),
actualColumn.typeDesc);

return columnPath;
} else {
return getColumnByName(name);
String[] parts = name.split("\\.");
// Some of the string can includes database name and table name and column name.
// For example, it can be 'default.table1.id'.
// Therefore, spilt string array length can be 3.
if (parts.length >= 2) {
return getColumnByQName(name);
} else {
return getColumnByName(name);
}
}
}

Expand Down Expand Up @@ -268,12 +295,46 @@ public int getColumnIdByName(String colName) {
}
return -1;
}

public List<Column> getColumns() {

/**
* Get root columns, meaning all columns except for nested fields.
*
* @return A list of root columns
*/
public List<Column> getRootColumns() {
return ImmutableList.copyOf(fields);
}

/**
* Get all columns, including all nested fields
*
* @return A list of all columns
*/
public List<Column> getAllColumns() {
final List<Column> columnList = TUtil.newList();

SchemaUtil.visitSchema(this, new ColumnVisitor() {
@Override
public void visit(int depth, List<String> path, Column column) {
if (path.size() > 0) {
String parentPath = StringUtils.join(path, NestedPathUtil.PATH_DELIMITER);
String currentPath = parentPath + NestedPathUtil.PATH_DELIMITER + column.getSimpleName();
columnList.add(new Column(currentPath, column.getTypeDesc()));
} else {
columnList.add(column);
}
}
});

return columnList;
}

public boolean contains(String name) {
// TODO - It's a hack
if (NestedPathUtil.isPath(name)) {
return (getColumn(name) != null);
}

if (fieldsByQualifiedName.containsKey(name)) {
return true;
}
Expand All @@ -288,6 +349,11 @@ public boolean contains(String name) {
}

public boolean contains(Column column) {
// TODO - It's a hack
if (NestedPathUtil.isPath(column.getQualifiedName())) {
return (getColumn(column.getQualifiedName()) != null);
}

if (column.hasQualifier()) {
return fieldsByQualifiedName.containsKey(column.getQualifiedName());
} else {
Expand All @@ -314,7 +380,24 @@ public boolean containsByName(String colName) {
}

public boolean containsAll(Collection<Column> columns) {
return fields.containsAll(columns);
boolean containFlag = true;

for (Column c :columns) {
if (NestedPathUtil.isPath(c.getSimpleName())) {
if (contains(c.getQualifiedName())) {
containFlag &= true;
} else {
String[] paths = c.getQualifiedName().split("/");
boolean existRootPath = contains(paths[0]);
boolean existLeafPath = getColumn(c.getSimpleName()) != null;
containFlag &= existRootPath && existLeafPath;
}
} else {
containFlag &= fields.contains(c);
}
}

return containFlag;
}

public synchronized Schema addColumn(String name, TypeDesc typeDesc) {
Expand Down Expand Up @@ -351,7 +434,7 @@ public synchronized void addColumn(Column column) {
}

public synchronized void addColumns(Schema schema) {
for(Column column : schema.getColumns()) {
for(Column column : schema.getRootColumns()) {
addColumn(column);
}
}
Expand Down Expand Up @@ -396,7 +479,7 @@ public SchemaProtoBuilder(SchemaProto.Builder builder) {
}

@Override
public void visit(int depth, Column column) {
public void visit(int depth, List<String> path, Column column) {

if (column.getDataType().getType() == Type.RECORD) {
DataType.Builder updatedType = DataType.newBuilder(column.getDataType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@

package org.apache.tajo.catalog;

import org.apache.tajo.util.TUtil;

import java.util.List;

import static org.apache.tajo.common.TajoDataTypes.DataType;
import static org.apache.tajo.common.TajoDataTypes.Type;

Expand All @@ -34,12 +38,12 @@ public class SchemaUtil {
static int tmpColumnSeq = 0;
public static Schema merge(Schema left, Schema right) {
Schema merged = new Schema();
for(Column col : left.getColumns()) {
for(Column col : left.getRootColumns()) {
if (!merged.containsByQualifiedName(col.getQualifiedName())) {
merged.addColumn(col);
}
}
for(Column col : right.getColumns()) {
for(Column col : right.getRootColumns()) {
if (merged.containsByQualifiedName(col.getQualifiedName())) {
merged.addColumn("?fake" + (tmpColumnSeq++), col.getDataType());
} else {
Expand All @@ -59,7 +63,7 @@ public static Schema merge(Schema left, Schema right) {
*/
public static Schema getNaturalJoinColumns(Schema left, Schema right) {
Schema common = new Schema();
for (Column outer : left.getColumns()) {
for (Column outer : left.getRootColumns()) {
if (!common.containsByName(outer.getSimpleName()) && right.containsByName(outer.getSimpleName())) {
common.addColumn(new Column(outer.getSimpleName(), outer.getDataType()));
}
Expand Down Expand Up @@ -113,7 +117,7 @@ public static <T extends Schema> T clone(Schema schema) {
* Column visitor interface
*/
public static interface ColumnVisitor {
public void visit(int depth, Column column);
public void visit(int depth, List<String> path, Column column);
}

/**
Expand All @@ -122,8 +126,8 @@ public static interface ColumnVisitor {
* @param function
*/
public static void visitSchema(Schema schema, ColumnVisitor function) {
for(Column col : schema.getColumns()) {
visitInDepthFirstOrder(0, function, col);
for(Column col : schema.getRootColumns()) {
visitInDepthFirstOrder(0, NestedPathUtil.ROOT_PATH, function, col);
}
}

Expand All @@ -134,14 +138,21 @@ public static void visitSchema(Schema schema, ColumnVisitor function) {
* @param function Visitor
* @param column Current visiting column
*/
private static void visitInDepthFirstOrder(int depth, ColumnVisitor function, Column column) {
private static void visitInDepthFirstOrder(int depth,
final List<String> path,
ColumnVisitor function,
Column column) {

if (column.getDataType().getType() == Type.RECORD) {
for (Column nestedColumn : column.typeDesc.nestedRecordSchema.getColumns()) {
visitInDepthFirstOrder(depth + 1, function, nestedColumn);
for (Column nestedColumn : column.typeDesc.nestedRecordSchema.getRootColumns()) {
List<String> newPath = TUtil.newList(path);
newPath.add(column.getQualifiedName());

visitInDepthFirstOrder(depth + 1, newPath, function, nestedColumn);
}
function.visit(depth, column);
function.visit(depth, path, column);
} else {
function.visit(depth, column);
function.visit(depth, path, column);
}
}

Expand Down
Loading