Author: jbellis Date: Mon Oct 11 13:52:53 2010 New Revision: 1021348 URL: http://svn.apache.org/viewvc?rev=1021348&view=rev Log: add cli support for schema modification. patch by Pavel Yaskevich; reviewed by jbellis for CASSANDRA-1584
Modified: cassandra/trunk/CHANGES.txt cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java cassandra/trunk/src/java/org/apache/cassandra/cli/CliCompiler.java cassandra/trunk/src/java/org/apache/cassandra/cli/CliMain.java cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java Modified: cassandra/trunk/CHANGES.txt URL: http://svn.apache.org/viewvc/cassandra/trunk/CHANGES.txt?rev=1021348&r1=1021347&r2=1021348&view=diff ============================================================================== --- cassandra/trunk/CHANGES.txt (original) +++ cassandra/trunk/CHANGES.txt Mon Oct 11 13:52:53 2010 @@ -25,6 +25,7 @@ dev * add ColumnDef support to cli (CASSANDRA-1583) * reduce index sample time by 75% (CASSANDRA-1572) * add cli support for column metadata (CASSANDRA-1578) + * add cli support for schema modification (CASSANDRA-1584) 0.7-beta2 Modified: cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g?rev=1021348&r1=1021347&r2=1021348&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cli/Cli.g Mon Oct 11 13:52:53 2010 @@ -52,7 +52,9 @@ tokens { NODE_DEL_KEYSPACE; NODE_DEL_COLUMN_FAMILY; NODE_RENAME_KEYSPACE; + NODE_UPDATE_KEYSPACE; NODE_RENAME_COLUMN_FAMILY; + NODE_UPDATE_COLUMN_FAMILY; // Internal Nodes. NODE_COLUMN_ACCESS; @@ -101,8 +103,10 @@ statement | exitStatement | countStatement | describeTable - | addColumnFamily | addKeyspace + | addColumnFamily + | updateKeyspace + | updateColumnFamily | delColumnFamily | delKeyspace | renameColumnFamily @@ -144,8 +148,12 @@ helpStatement -> ^(NODE_HELP NODE_SHOW_VERSION) | K_HELP K_CREATE K_TABLE -> ^(NODE_HELP NODE_ADD_KEYSPACE) + | K_HELP K_UPDATE K_TABLE + -> ^(NODE_HELP NODE_UPDATE_KEYSPACE) | K_HELP K_CREATE K_COLUMN K_FAMILY -> ^(NODE_HELP NODE_ADD_COLUMN_FAMILY) + | K_HELP K_UPDATE K_COLUMN K_FAMILY + -> ^(NODE_HELP NODE_UPDATE_COLUMN_FAMILY) | K_HELP K_DROP K_TABLE -> ^(NODE_HELP NODE_DEL_KEYSPACE) | K_HELP K_DROP K_COLUMN K_FAMILY @@ -214,6 +222,16 @@ addColumnFamily -> ^(NODE_ADD_COLUMN_FAMILY keyValuePairExpr) ; +updateKeyspace + : K_UPDATE K_TABLE keyValuePairExpr + -> ^(NODE_UPDATE_KEYSPACE keyValuePairExpr) + ; + +updateColumnFamily + : K_UPDATE K_COLUMN K_FAMILY keyValuePairExpr + -> ^(NODE_UPDATE_COLUMN_FAMILY keyValuePairExpr) + ; + delKeyspace : K_DROP K_TABLE keyspace -> ^(NODE_DEL_KEYSPACE keyspace) @@ -376,6 +394,7 @@ K_COLUMN: 'COLUMN'; K_FAMILY: 'FAMILY'; K_WITH: 'WITH'; K_AND: 'AND'; +K_UPDATE: 'UPDATE'; // private syntactic rules fragment Modified: cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java?rev=1021348&r1=1021347&r2=1021348&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java Mon Oct 11 13:52:53 2010 @@ -67,6 +67,8 @@ public class CliClient private String username = null; private Map<String, KsDef> keyspacesMap = new HashMap<String, KsDef>(); + private final String DEFAULT_PLACEMENT_STRATEGY = "org.apache.cassandra.locator.SimpleStrategy"; + public CliClient(CliSessionState cliSessionState, Cassandra.Client thriftClient) { css_ = cliSessionState; @@ -100,11 +102,17 @@ public class CliClient case CliParser.NODE_THRIFT_COUNT: executeCount(ast); break; + case CliParser.NODE_ADD_KEYSPACE: + executeAddKeyspace(ast.getChild(0)); + break; case CliParser.NODE_ADD_COLUMN_FAMILY: - executeAddColumnFamily(ast); + executeAddColumnFamily(ast.getChild(0)); break; - case CliParser.NODE_ADD_KEYSPACE: - executeAddKeyspace(ast); + case CliParser.NODE_UPDATE_KEYSPACE: + executeUpdateKeyspace(ast.getChild(0)); + break; + case CliParser.NODE_UPDATE_COLUMN_FAMILY: + executeUpdateColumnFamily(ast.getChild(0)); break; case CliParser.NODE_DEL_COLUMN_FAMILY: executeDelColumnFamily(ast); @@ -125,7 +133,7 @@ public class CliClient executeShowVersion(); break; case CliParser.NODE_SHOW_TABLES: - executeShowTables(ast); + executeShowTables(); break; case CliParser.NODE_DESCRIBE_TABLE: executeDescribeTable(ast); @@ -223,7 +231,25 @@ public class CliClient css_.out.println("create keyspace foo with replication_factor = 3 and "); css_.out.println(" placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy'"); break; - + + case CliParser.NODE_UPDATE_KEYSPACE: + css_.out.println("update keyspace <keyspace>"); + css_.out.println("update keyspace <keyspace> with <att1>=<value1>"); + css_.out.println("update keyspace <keyspace> with <att1>=<value1> and <att2>=<value2> ...\n"); + css_.out.println("Update a keyspace with the specified values for the given set of attributes.\n"); + css_.out.println("valid attributes are:"); + css_.out.println(" replication_factor: to how many nodes should entries to this keyspace be"); + css_.out.println(" replicated. Valid entries are integers greater than 0."); + css_.out.println(" placement_strategy: the fully qualified class used to place replicas in"); + css_.out.println(" this keyspace. Valid values are"); + css_.out.println(" org.apache.cassandra.locator.SimpleStrategy,"); + css_.out.println(" org.apache.cassandra.locator.NetworkTopologyStrategy,"); + css_.out.println(" and org.apache.cassandra.locator.OldNetworkTopologyStrategy\n"); + css_.out.println("example:"); + css_.out.println("update keyspace foo with replication_factor = 2 and "); + css_.out.println(" placement_strategy = 'org.apache.cassandra.locator.LocalStrategy'"); + break; + case CliParser.NODE_ADD_COLUMN_FAMILY: css_.out.println("create column family Bar"); css_.out.println("create column family Bar with <att1>=<value1>"); @@ -249,14 +275,37 @@ public class CliClient css_.out.println(" Valid attributes: column_name, validation_class (see comparator),"); css_.out.println(" index_type (integer), index_name."); css_.out.println("example:\n"); - css_.out.println("create column family bar with column_type = 'Super' and comparator = 'AsciiType'"); + css_.out.println("create column family Bar with column_type = 'Super' and comparator = 'AsciiType'"); css_.out.println(" and rows_cached = 10000"); - css_.out.println("create column family baz with comparator = 'LongType' and rows_cached = 10000"); - css_.out.print("create column family foo with comparator=LongType and column_metadata="); + css_.out.println("create column family Baz with comparator = 'LongType' and rows_cached = 10000"); + css_.out.print("create column family Foo with comparator=LongType and column_metadata="); css_.out.print("[{ column_name:Test, validation_class:IntegerType, index_type:0, index_name:IdxName"); css_.out.println("}, { column_name:'other name', validation_class:LongType }]"); break; - + + case CliParser.NODE_UPDATE_COLUMN_FAMILY: + css_.out.println("update column family Bar"); + css_.out.println("update column family Bar with <att1>=<value1>"); + css_.out.println("update column family Bar with <att1>=<value1> and <att2>=<value2>...\n"); + css_.out.println("Update a column family with the specified values for the given set of"); + css_.out.println("attributes. Note that you must be using a keyspace.\n"); + css_.out.println("valid attributes are:"); + css_.out.println(" - comment: Human-readable column family description. Any string is valid."); + css_.out.println(" - rows_cached: Number of rows to cache"); + css_.out.println(" - preload_row_cache: Set to true to automatically load the row cache"); + css_.out.println(" - key_cache_size: Number of keys to cache"); + css_.out.println(" - read_repair_chance: Valid values for this attribute are any number"); + css_.out.println(" between 0.0 and 1.0\n"); + css_.out.println(" - column_metadata: Metadata which describes columns of column family."); + css_.out.println(" Supported format is [{ k:v, k:v, ... }, { ... }, ...]"); + css_.out.println(" Valid attributes: column_name, validation_class (see comparator),"); + css_.out.println(" index_type (integer), index_name."); + css_.out.println("example:\n"); + css_.out.print("update column family Foo with column_metadata="); + css_.out.print("[{ column_name:Test, validation_class:IntegerType, index_type:0, index_name:IdxName"); + css_.out.println("}] and rows_cached=100 and comment='this is helpful comment.'"); + break; + case CliParser.NODE_RENAME_KEYSPACE: css_.out.println("rename keyspace <old_name> <new_name>\n"); css_.out.println("Renames the specified keyspace with the given new name.\n"); @@ -343,9 +392,13 @@ public class CliClient css_.out.println("show keyspaces Show list of keyspaces."); css_.out.println("show api version Show server API version."); css_.out.println("create keyspace <keyspace> [with <att1>=<value1> [and <att2>=<value2> ...]]"); - css_.out.println(" Add a new keyspace with the specified attribute and value(s)."); + css_.out.println(" Add a new keyspace with the specified attribute(s) and value(s)."); + css_.out.println("update keyspace <keyspace> [with <att1>=<value1> [and <att2>=<value2> ...]]"); + css_.out.println(" Update a keyspace with the specified attribute(s) and value(s)."); css_.out.println("create column family <cf> [with <att1>=<value1> [and <att2>=<value2> ...]]"); - css_.out.println(" Create a new column family with the specified attribute and value(s)."); + css_.out.println(" Create a new column family with the specified attribute(s) and value(s)."); + css_.out.println("update column family <cf> [with <att1>=<value1> [and <att2>=<value2> ...]]"); + css_.out.println(" Update a column family with the specified attribute(s) and value(s)."); css_.out.println("drop keyspace <keyspace> Delete a keyspace."); css_.out.println("drop column family <cf> Delete a column family."); css_.out.println("rename keyspace <keyspace> <keyspace_new_name> Rename a keyspace."); @@ -672,89 +725,180 @@ public class CliClient /** * Add a keyspace - * @throws TException - * @throws InvalidRequestException - * @throws NotFoundException + * @param statement - a token tree representing current statement */ - private void executeAddKeyspace(CommonTree ast) throws TException, InvalidRequestException, NotFoundException + private void executeAddKeyspace(Tree statement) { if (!CliMain.isConnected()) { return; } - CommonTree newKSSpec = (CommonTree)ast.getChild(0); + + //defaults + final List<CfDef> columnList = new LinkedList<CfDef>(); + + // first value is the keyspace name, after that it is all key=value + final String keyspaceName = statement.getChild(0).getText(); + final KsDef ksDef = new KsDef(keyspaceName, DEFAULT_PLACEMENT_STRATEGY, 1, columnList); - //parser send the keyspace, plus a series of key value pairs, ie should always be an odd number... - assert(newKSSpec.getChildCount() > 0); - assert(newKSSpec.getChildCount() % 2 == 1); + try + { + css_.out.println(thriftClient_.system_add_keyspace(updateKsDefAttributes(statement, ksDef))); + keyspacesMap.put(keyspaceName, thriftClient_.describe_keyspace(keyspaceName)); + } + catch (InvalidRequestException e) + { + throw new RuntimeException(e.getWhy()); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage(), e); + } + } - //defaults - String replicaPlacementStrategy = "org.apache.cassandra.locator.SimpleStrategy"; - int replicationFactor = 1; - /* - * first value is the keyspace name, after that it is all key=value - */ - String keyspaceName = newKSSpec.getChild(0).getText(); - int argumentLength = newKSSpec.getChildCount(); + /** + * Add a column family + * @param statement - a token tree representing current statement + */ + private void executeAddColumnFamily(Tree statement) + { + if (!CliMain.isConnected() || !hasKeySpace()) + { + return; + } + + // first value is the column family name, after that it is all key=value + final String columnFamilyName = statement.getChild(0).getText(); + final CfDef cfDef = new CfDef(keySpace, columnFamilyName); - for(int i = 1; i < argumentLength; i = i + 2) + try { - AddKeyspaceArgument mArgument = AddKeyspaceArgument.valueOf(newKSSpec.getChild(i).getText().toUpperCase()); - String mValue = newKSSpec.getChild(i + 1).getText(); + css_.out.println(thriftClient_.system_add_column_family(updateCfDefAttributes(statement, cfDef))); + keyspacesMap.put(keySpace, thriftClient_.describe_keyspace(keySpace)); + } + catch (InvalidRequestException e) + { + throw new RuntimeException(e.getWhy()); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage(), e); + } + } + + /** + * Update existing keyspace identified by name + * @param statement - tree represeting statement + */ + private void executeUpdateKeyspace(final Tree statement) + { + if (!CliMain.isConnected()) + { + return; + } + + final String keyspaceName = statement.getChild(0).getText(); + + try + { + final KsDef currentKsDef = getKSMetaData(keyspaceName); + final KsDef updatedKsDef = updateKsDefAttributes(statement, currentKsDef); + + css_.out.println(thriftClient_.system_update_keyspace(updatedKsDef)); + keyspacesMap.put(keyspaceName, thriftClient_.describe_keyspace(keyspaceName)); + } + catch (InvalidRequestException e) + { + throw new RuntimeException(e.getWhy()); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage(), e); + } + } + + /** + * Update existing column family identified by name + * @param statement - tree represeting statement + */ + private void executeUpdateColumnFamily(final Tree statement) + { + if (!CliMain.isConnected() || !hasKeySpace()) + { + return; + } + + final String columnFamilyName = statement.getChild(0).getText(); + final CfDef cfDef = getCfDef(columnFamilyName); + + try + { + css_.out.println(thriftClient_.system_update_column_family(updateCfDefAttributes(statement, cfDef))); + keyspacesMap.put(keySpace, thriftClient_.describe_keyspace(keySpace)); + } + catch (InvalidRequestException e) + { + throw new RuntimeException(e.getWhy()); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage(), e); + } + } + + /** + * Used to update keyspace definition attributes + * @param statement - ANTRL tree representing current statement + * @param ksDefToUpdate - keyspace definition to update + * @return ksDef - updated keyspace definition + */ + private KsDef updateKsDefAttributes(final Tree statement, final KsDef ksDefToUpdate) + { + final KsDef ksDef = new KsDef(ksDefToUpdate); + + // removing all column definitions - thrift system_update_keyspace method requires that + ksDef.setCf_defs(new LinkedList<CfDef>()); + + for(int i = 1; i < statement.getChildCount(); i += 2) + { + final String currentStatement = statement.getChild(i).getText().toUpperCase(); + final AddKeyspaceArgument mArgument = AddKeyspaceArgument.valueOf(currentStatement); + final String mValue = statement.getChild(i + 1).getText(); switch(mArgument) { - case PLACEMENT_STRATEGY: - replicaPlacementStrategy = CliUtils.unescapeSQLString(mValue); + case PLACEMENT_STRATEGY: + ksDef.setStrategy_class(CliUtils.unescapeSQLString(mValue)); break; case REPLICATION_FACTOR: - replicationFactor = Integer.parseInt( mValue); + ksDef.setReplication_factor(Integer.parseInt(mValue)); break; default: //must match one of the above or we'd throw an exception at the valueOf statement above. assert(false); } } - List<CfDef> mList = new LinkedList<CfDef>(); - KsDef ks_def = new KsDef(keyspaceName, replicaPlacementStrategy, replicationFactor, mList); - css_.out.println(thriftClient_.system_add_keyspace(ks_def)); - keyspacesMap.put(keyspaceName, thriftClient_.describe_keyspace(keyspaceName)); + return ksDef; } - - + /** - * Add a column family - * @throws TException - * @throws InvalidRequestException - * @throws NotFoundException + * Update column family definition attributes + * @param statement - ANTLR tree representing current statement + * @param cfDefToUpdate - column family definition to apply updates on + * @return cfDef - updated column family definition */ - private void executeAddColumnFamily(CommonTree ast) throws TException, InvalidRequestException, NotFoundException + private CfDef updateCfDefAttributes(final Tree statement, final CfDef cfDefToUpdate) { - if (!CliMain.isConnected() || !hasKeySpace()) - { - return; - } + final CfDef cfDef = new CfDef(cfDefToUpdate); - CommonTree newCFTree = (CommonTree)ast.getChild(0); - //parser send the keyspace, plus a series of key value pairs, ie should always be an odd number... - assert(newCFTree.getChildCount() > 0); - assert(newCFTree.getChildCount() % 2 == 1); - - /* - * first value is the keyspace name, after that it is all key=value - */ - final String columnName = newCFTree.getChild(0).getText(); - final int argumentLength = newCFTree.getChildCount(); - final CfDef cfDef = new CfDef(keySpace, columnName); - - for(int i = 1; i < argumentLength; i = i + 2) + for(int i = 1; i < statement.getChildCount(); i += 2) { - AddColumnFamilyArgument mArgument = AddColumnFamilyArgument.valueOf(newCFTree.getChild(i).getText().toUpperCase()); - String mValue = newCFTree.getChild(i + 1).getText(); - + final String currentArgument = statement.getChild(i).getText().toUpperCase(); + final AddColumnFamilyArgument mArgument = AddColumnFamilyArgument.valueOf(currentArgument); + final String mValue = statement.getChild(i + 1).getText(); switch(mArgument) { @@ -795,31 +939,32 @@ public class CliClient break; case COLUMN_METADATA: - final Tree arrayOfMetaAttributes = newCFTree.getChild(i + 1); - + final Tree arrayOfMetaAttributes = statement.getChild(i + 1); + if (!arrayOfMetaAttributes.getText().equals("ARRAY")) { throw new RuntimeException("'column_metadata' format - [{ k:v, k:v, ..}, { ... }, ...]"); } - + cfDef.setColumn_metadata(getCFColumnMetaFromTree(arrayOfMetaAttributes)); break; - + default: //must match one of the above or we'd throw an exception at the valueOf statement above. assert(false); } } - css_.out.println(thriftClient_.system_add_column_family(cfDef)); - keyspacesMap.put(keySpace, thriftClient_.describe_keyspace(keySpace)); + + return cfDef; } /** * Delete a keyspace - * @throws TException - * @throws InvalidRequestException - * @throws NotFoundException + * @param ast - a token tree representing current statement + * @throws TException - exception + * @throws InvalidRequestException - exception + * @throws NotFoundException - exception */ private void executeDelKeyspace(CommonTree ast) throws TException, InvalidRequestException, NotFoundException { @@ -835,9 +980,10 @@ public class CliClient /** * Delete a column family - * @throws TException - * @throws InvalidRequestException - * @throws NotFoundException + * @param ast - a token tree representing current statement + * @throws TException - exception + * @throws InvalidRequestException - exception + * @throws NotFoundException - exception */ private void executeDelColumnFamily(CommonTree ast) throws TException, InvalidRequestException, NotFoundException { @@ -850,10 +996,11 @@ public class CliClient } /** - * Add a column family - * @throws TException - * @throws InvalidRequestException - * @throws NotFoundException + * Rename existing keyspace + * @param ast - a token tree representing current statement + * @throws TException - exception + * @throws InvalidRequestException - exception + * @throws NotFoundException - exception */ private void executeRenameKeyspace(CommonTree ast) throws TException, InvalidRequestException, NotFoundException { @@ -868,10 +1015,11 @@ public class CliClient } /** - * Add a column family - * @throws TException - * @throws InvalidRequestException - * @throws NotFoundException + * Rename existing column family + * @param ast - a token tree representing current statement + * @throws TException - exception + * @throws InvalidRequestException - exception + * @throws NotFoundException - exception */ private void executeRenameColumnFamily(CommonTree ast) throws TException, InvalidRequestException, NotFoundException { @@ -893,7 +1041,7 @@ public class CliClient } // process "show tables" statement - private void executeShowTables(CommonTree ast) throws TException, InvalidRequestException + private void executeShowTables() throws TException, InvalidRequestException { if (!CliMain.isConnected()) return; @@ -997,22 +1145,18 @@ public class CliClient { css_.err.println("Exception during authentication to the cassandra node: " + "verify keyspace exists, and you are using correct credentials."); - return; } catch (AuthorizationException e) { css_.err.println("You are not authorized to use keyspace: " + tableName); - return; } catch (InvalidRequestException e) { css_.err.println(tableName + " does not exist."); - return; } catch (NotFoundException e) { css_.err.println(tableName + " does not exist."); - return; } catch (TException e) { @@ -1020,7 +1164,6 @@ public class CliClient e.printStackTrace(); css_.err.println("Login failure. Did you specify 'keyspace', 'username' and 'password'?"); - return; } } @@ -1361,4 +1504,5 @@ public class CliClient return null; } + } Modified: cassandra/trunk/src/java/org/apache/cassandra/cli/CliCompiler.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cli/CliCompiler.java?rev=1021348&r1=1021347&r2=1021348&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cli/CliCompiler.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cli/CliCompiler.java Mon Oct 11 13:52:53 2010 @@ -90,15 +90,11 @@ public class CliCompiler public static String getColumnFamily(CommonTree astNode) { - assert(astNode.getType() == CliParser.NODE_COLUMN_ACCESS); - return astNode.getChild(0).getText(); } public static String getKey(CommonTree astNode) { - assert(astNode.getType() == CliParser.NODE_COLUMN_ACCESS); - return CliUtils.unescapeSQLString(astNode.getChild(1).getText()); } Modified: cassandra/trunk/src/java/org/apache/cassandra/cli/CliMain.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cli/CliMain.java?rev=1021348&r1=1021347&r2=1021348&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cli/CliMain.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cli/CliMain.java Mon Oct 11 13:52:53 2010 @@ -36,14 +36,11 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import static org.apache.cassandra.db.Table.SYSTEM_TABLE; - /** * Cassandra Command Line Interface (CLI) Main */ public class CliMain { - public final static String PROMPT = "cassandra"; public final static String HISTORYFILE = ".cassandra.history"; private static TTransport transport_ = null; Modified: cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java?rev=1021348&r1=1021347&r2=1021348&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/cli/CliUtils.java Mon Oct 11 13:52:53 2010 @@ -26,6 +26,8 @@ public class CliUtils /** * Strips leading and trailing "'" characters, and handles * and escaped characters such as \n, \r, etc. + * @param b - string to unescape + * @return String - unexspaced string */ public static String unescapeSQLString(String b) { @@ -92,4 +94,5 @@ public class CliUtils return sb.toString(); } + }