Author: brandonwilliams
Date: Mon Aug  8 21:08:04 2011
New Revision: 1155100

URL: http://svn.apache.org/viewvc?rev=1155100&view=rev
Log:
Add 'show creates' commands to the cli to export schema.
Patch by Aaron Morton, reviewed by xedin for CASSANDRA-2221

Modified:
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/Cli.g
    
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java
    
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliCompleter.java
    
cassandra/branches/cassandra-0.8/src/resources/org/apache/cassandra/cli/CliHelp.yaml
    
cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/cli/CliTest.java

Modified: 
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/Cli.g
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/Cli.g?rev=1155100&r1=1155099&r2=1155100&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/Cli.g 
(original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/Cli.g 
Mon Aug  8 21:08:04 2011
@@ -44,6 +44,7 @@ tokens {
     NODE_SHOW_CLUSTER_NAME;
     NODE_SHOW_VERSION;
     NODE_SHOW_KEYSPACES;
+    NODE_SHOW_SCHEMA;
     NODE_THRIFT_GET;
     NODE_THRIFT_GET_WITH_CONDITIONS;
     NODE_THRIFT_SET;
@@ -191,6 +192,8 @@ helpStatement
         -> ^(NODE_HELP NODE_SHOW_CLUSTER_NAME)
     | HELP SHOW KEYSPACES 
         -> ^(NODE_HELP NODE_SHOW_KEYSPACES)
+    | HELP SHOW SCHEMA
+            -> ^(NODE_HELP NODE_SHOW_SCHEMA)
     | HELP SHOW API_VERSION
         -> ^(NODE_HELP NODE_SHOW_VERSION)
     | HELP CREATE KEYSPACE 
@@ -284,6 +287,7 @@ showStatement
     : showClusterName
     | showVersion
     | showKeyspaces
+    | showSchema
     ;
 
 listStatement
@@ -356,6 +360,11 @@ showKeyspaces
         -> ^(NODE_SHOW_KEYSPACES)
     ;
 
+showSchema
+    : SHOW SCHEMA (keyspace)?
+        -> ^(NODE_SHOW_SCHEMA (keyspace)?)
+    ;
+
 describeTable
     : DESCRIBE KEYSPACE (keyspace)?
         -> ^(NODE_DESCRIBE_TABLE (keyspace)?)
@@ -573,6 +582,7 @@ TTL:         'TTL';
 CONSISTENCYLEVEL:   'CONSISTENCYLEVEL';
 INDEX:       'INDEX';
 ON:          'ON';
+SCHEMA:      'SCHEMA';
 
 IP_ADDRESS 
     : IntegerPositiveLiteral '.' IntegerPositiveLiteral '.' 
IntegerPositiveLiteral '.' IntegerPositiveLiteral

Modified: 
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java?rev=1155100&r1=1155099&r2=1155100&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java
 (original)
+++ 
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java
 Mon Aug  8 21:08:04 2011
@@ -26,6 +26,9 @@ import java.nio.ByteBuffer;
 import java.nio.charset.CharacterCodingException;
 import java.util.*;
 
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import org.apache.commons.lang.StringUtils;
 import com.google.common.base.Charsets;
 import com.google.common.base.Joiner;
 
@@ -71,7 +74,7 @@ public class CliClient
         COUNTERCOLUMN (CounterColumnType.instance);
 
         private AbstractType validator;
-        
+
         Function(AbstractType validator)
         {
             this.validator = validator;  
@@ -136,6 +139,8 @@ public class CliClient
     }
 
     private static final String DEFAULT_PLACEMENT_STRATEGY = 
"org.apache.cassandra.locator.NetworkTopologyStrategy";
+    private final String NEWLINE = System.getProperty("line.separator");
+    private final String TAB = "  ";
 
     private Cassandra.Client thriftClient = null;
     private CliSessionState sessionState  = null;
@@ -241,6 +246,9 @@ public class CliClient
                 case CliParser.NODE_SHOW_KEYSPACES:
                     executeShowKeySpaces();
                     break;
+                case CliParser.NODE_SHOW_SCHEMA:
+                    executeShowSchema(tree);
+                    break;
                 case CliParser.NODE_DESCRIBE_TABLE:
                     executeDescribeKeySpace(tree);
                     break;
@@ -1246,7 +1254,7 @@ public class CliClient
                 cfDef.setReplicate_on_write(Boolean.parseBoolean(mValue));
                 break;
             case ROW_CACHE_PROVIDER:
-                cfDef.setRow_cache_provider(mValue);
+                
cfDef.setRow_cache_provider(CliUtils.unescapeSQLString(mValue));
                 break;
             case KEY_VALIDATION_CLASS:
                 
cfDef.setKey_validation_class(CliUtils.unescapeSQLString(mValue));
@@ -1560,6 +1568,187 @@ public class CliClient
         }
     }
 
+    // SHOW SCHEMA
+    private void executeShowSchema(Tree statement) throws TException, 
InvalidRequestException
+    {
+        if (!CliMain.isConnected())
+            return;
+
+        final List<KsDef> keyspaces = thriftClient.describe_keyspaces();
+        Collections.sort(keyspaces, new KsDefNamesComparator());
+        final String keyspaceName = (statement.getChildCount() == 0)
+                                ? keySpace
+                                : CliCompiler.getKeySpace(statement, 
keyspaces);
+
+        Iterator<KsDef> ksIter;
+        if (keyspaceName != null)
+            ksIter = Collections2.filter(keyspaces, new Predicate<KsDef>()
+            {
+                public boolean apply(KsDef ksDef)
+                {
+                    return keyspaceName.equals(ksDef.name);
+                }
+            }).iterator();
+        else
+            ksIter = keyspaces.iterator();
+
+
+        final StringBuilder sb = new StringBuilder();
+        while (ksIter.hasNext())
+            showKeyspace(sb, ksIter.next());
+
+        sessionState.out.printf(sb.toString());
+    }
+
+    /**
+     * Creates a CLI script to create the Keyspace it's Column Families
+     * @param sb StringBuilder to write to.
+     * @param ksDef KsDef to create the cli script for.
+     */
+    private void showKeyspace(StringBuilder sb, KsDef ksDef)
+    {
+
+        sb.append("create keyspace " + ksDef.name);
+        if (ksDef.isSetReplication_factor())
+            writeAttr(sb, false, "replication_factor", 
ksDef.getReplication_factor());
+        writeAttr(sb, true, "placement_strategy", 
normaliseType(ksDef.strategy_class, "org.apache.cassandra.locator"));
+        if (ksDef.strategy_options != null && 
!ksDef.strategy_options.isEmpty())
+        {
+            final StringBuilder opts = new StringBuilder();
+            opts.append("[{");
+            String prefix = "";
+            for (Map.Entry<String, String> opt : 
ksDef.strategy_options.entrySet())
+            {
+                opts.append(prefix + CliUtils.escapeSQLString(opt.getKey()) + 
" : " + CliUtils.escapeSQLString(opt.getValue()));
+                prefix = ", ";
+            }
+            opts.append("}]");
+            writeAttrRaw(sb, false, "strategy_options", opts.toString());
+        }
+        sb.append(";" + NEWLINE);
+        sb.append(NEWLINE);
+
+        sb.append("use " + ksDef.name + ";");
+        sb.append(NEWLINE);
+        sb.append(NEWLINE);
+
+        Collections.sort(ksDef.cf_defs, new CfDefNamesComparator());
+        for (CfDef cfDef : ksDef.cf_defs)
+            showColumnFamily(sb, cfDef);
+        sb.append(NEWLINE);
+        sb.append(NEWLINE);
+    }
+
+    /**
+     * Creates a CLI script for the CfDef including meta data to the supplied 
StringBuilder.
+     * @param sb
+     * @param cfDef
+     */
+    private void showColumnFamily(StringBuilder sb, CfDef cfDef)
+    {
+        sb.append("create column family " + 
CliUtils.escapeSQLString(cfDef.name));
+
+        writeAttr(sb, true, "column_type", cfDef.column_type);
+        writeAttr(sb, false, "comparator", 
normaliseType(cfDef.comparator_type, "org.apache.cassandra.db.marshal"));
+        if (cfDef.column_type == "Super")
+            writeAttr(sb, false, "subcomparator", 
normaliseType(cfDef.subcomparator_type, "org.apache.cassandra.db.marshal"));
+        if (!StringUtils.isEmpty(cfDef.default_validation_class))
+            writeAttr(sb, false, "default_validation_class",
+                        normaliseType(cfDef.default_validation_class, 
"org.apache.cassandra.db.marshal"));
+        writeAttr(sb, false, "key_validation_class",
+                    normaliseType(cfDef.key_validation_class, 
"org.apache.cassandra.db.marshal"));
+        writeAttr(sb, false, "memtable_operations", 
cfDef.memtable_operations_in_millions);
+        writeAttr(sb, false, "memtable_throughput", 
cfDef.memtable_throughput_in_mb);
+        writeAttr(sb, false, "memtable_flush_after", 
cfDef.memtable_flush_after_mins);
+        writeAttr(sb, false, "rows_cached", cfDef.row_cache_size);
+        writeAttr(sb, false, "row_cache_save_period", 
cfDef.row_cache_save_period_in_seconds);
+        writeAttr(sb, false, "keys_cached", cfDef.key_cache_size);
+        writeAttr(sb, false, "key_cache_save_period", 
cfDef.key_cache_save_period_in_seconds);
+        writeAttr(sb, false, "read_repair_chance", cfDef.read_repair_chance);
+        writeAttr(sb, false, "gc_grace", cfDef.gc_grace_seconds);
+        writeAttr(sb, false, "min_compaction_threshold", 
cfDef.min_compaction_threshold);
+        writeAttr(sb, false, "max_compaction_threshold", 
cfDef.max_compaction_threshold);
+        writeAttr(sb, false, "replicate_on_write", cfDef.replicate_on_write);
+        writeAttr(sb, false, "row_cache_provider", 
normaliseType(cfDef.row_cache_provider, "org.apache.cassandra.cache"));
+
+        if (!StringUtils.isEmpty(cfDef.comment))
+            writeAttr(sb, false, "comment", cfDef.comment);
+
+        if (!cfDef.column_metadata.isEmpty())
+        {
+            StringBuilder colSb = new StringBuilder();
+            colSb.append("[");
+            boolean first = true;
+            for (ColumnDef colDef : cfDef.column_metadata)
+            {
+                if (!first)
+                    colSb.append(",");
+                first = false;
+                showColumnMeta(colSb, cfDef, colDef);
+            }
+            colSb.append("]");
+            writeAttrRaw(sb, false, "column_metadata", colSb.toString());
+        }
+        sb.append(";");
+        sb.append(NEWLINE);
+        sb.append(NEWLINE);
+    }
+
+    /**
+     * Writes the supplied ColumnDef to the StringBuilder as a cli script.
+     * @param sb
+     * @param cfDef
+     * @param colDef
+     */
+    private void showColumnMeta(StringBuilder sb, CfDef cfDef, ColumnDef 
colDef)
+    {
+        sb.append(NEWLINE + TAB + TAB + "{");
+
+        final AbstractType comparator = getFormatType((cfDef.column_type == 
"Super")
+                                                        ? 
cfDef.subcomparator_type
+                                                        : 
cfDef.comparator_type);
+        sb.append("column_name : '" + 
CliUtils.escapeSQLString(comparator.getString(colDef.name)) + "'," + NEWLINE);
+        String validationClass = normaliseType(colDef.validation_class, 
"org.apache.cassandra.db.marshal");
+        sb.append(TAB + TAB + "validation_class : " + 
CliUtils.escapeSQLString(validationClass));
+        if (colDef.isSetIndex_name())
+        {
+            sb.append("," + NEWLINE);
+            sb.append(TAB + TAB + "index_name : '" + 
CliUtils.escapeSQLString(colDef.index_name) + "'," + NEWLINE);
+            sb.append(TAB + TAB + "index_type : " + 
CliUtils.escapeSQLString(Integer.toString(colDef.index_type.getValue())));
+
+        }
+        sb.append("}");
+    }
+
+    private String normaliseType(String path, String expectedPackage)
+    {
+        if (path.startsWith(expectedPackage))
+            return path.substring(expectedPackage.length() + 1);
+
+        return path;
+    }
+
+    private void writeAttr(StringBuilder sb, boolean first, String name, 
Boolean value)
+    {
+        writeAttrRaw(sb, first, name, value.toString());
+    }
+    private void writeAttr(StringBuilder sb, boolean first, String name, 
Number value)
+    {
+        writeAttrRaw(sb, first, name, value.toString());
+    }
+
+    private void writeAttr(StringBuilder sb, boolean first, String name, 
String value)
+    {
+        writeAttrRaw(sb, first, name, "'" + CliUtils.escapeSQLString(value) + 
"'");
+    }
+
+    private void writeAttrRaw(StringBuilder sb, boolean first, String name, 
String value)
+    {
+        sb.append(NEWLINE + TAB);
+        sb.append(first ? "with " : "and ");
+        sb.append(name + " = ");
+        sb.append(value);
+    }
     /**
      * Returns true if this.keySpace is set, false otherwise
      * @return boolean

Modified: 
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliCompleter.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliCompleter.java?rev=1155100&r1=1155099&r2=1155100&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliCompleter.java
 (original)
+++ 
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliCompleter.java
 Mon Aug  8 21:08:04 2011
@@ -29,6 +29,7 @@ public class CliCompleter extends Simple
             "quit",
             "show cluster name",
             "show keyspaces",
+            "show schema",
             "show api version",
             "create keyspace",
             "create column family",
@@ -45,6 +46,7 @@ public class CliCompleter extends Simple
             "help quit",
             "help show cluster name",
             "help show keyspaces",
+            "help show schema",
             "help show api version",
             "help create keyspace",
             "help create column family",

Modified: 
cassandra/branches/cassandra-0.8/src/resources/org/apache/cassandra/cli/CliHelp.yaml
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/resources/org/apache/cassandra/cli/CliHelp.yaml?rev=1155100&r1=1155099&r2=1155100&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.8/src/resources/org/apache/cassandra/cli/CliHelp.yaml
 (original)
+++ 
cassandra/branches/cassandra-0.8/src/resources/org/apache/cassandra/cli/CliHelp.yaml
 Mon Aug  8 21:08:04 2011
@@ -52,6 +52,7 @@ help: |
     show api version        Show the server API version.
     show cluster name       Show the cluster name.
     show keyspaces          Show all keyspaces and their column families.
+    show schema             Show a cli script to create keyspaces and column 
families.
     truncate                Drop the data in a column family.
     update column family    Update the settings for a column family.
     update keyspace         Update the settings for a keyspace.
@@ -116,7 +117,8 @@ commands:
         use Keyspace1 user 'badpasswd';
     - name: NODE_DESCRIBE_TABLE
       help: |
-        describe keyspace (<keyspace>)?;
+        describe keyspace;
+        describe keyspace <keyspace>;
 
         Describes the settings for the current or named keyspace, and the 
settings
         for all column families in the keyspace.
@@ -126,7 +128,7 @@ commands:
 
         Examples:
         describe keyspace;
-        describe keyspace system;
+        describe keyspace Keyspace1;
     - name: NODE_DESCRIBE_CLUSTER
       help: |
         describe cluster;
@@ -177,6 +179,22 @@ commands:
 
         Examples:
         show keyspaces;
+    - name: NODE_SHOW_SCHEMA
+      help: |
+        show schema;
+        show schema <keyspace>;
+
+        Creates a CLI script to create the current, specified or all keyspaces
+        and their column families.
+
+        Optional Parameters:
+        - keyspace: Name of the keyspace to create the script for. If omitted
+        the current keyspace is used, if there is no current keyspace all
+        keyspaces are considered.
+
+        Examples:
+        show schema;
+        show schema Keyspace1;
     - name: NODE_ADD_KEYSPACE
       help: |
         create keyspace <keyspace>;

Modified: 
cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/cli/CliTest.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/cli/CliTest.java?rev=1155100&r1=1155099&r2=1155100&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/cli/CliTest.java
 (original)
+++ 
cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/cli/CliTest.java
 Mon Aug  8 21:08:04 2011
@@ -166,6 +166,7 @@ public class CliTest extends CleanupHelp
         "help QUIT",
         "help show cluster name",
         "help show keyspaces",
+        "help show schema",
         "help show api version",
         "help create keyspace",
         "HELP update KEYSPACE",
@@ -181,7 +182,9 @@ public class CliTest extends CleanupHelp
         "HELP TRUNCATE",
         "help assume",
         "HELP",
-        "?"
+        "?",
+        "show schema",
+        "show schema TestKeySpace"
     };
    
     @Test
@@ -270,4 +273,4 @@ public class CliTest extends CleanupHelp
         assertEquals(unescaped, CliUtils.unescapeSQLString("'" + escaped + 
"'"));
         assertEquals(escaped, CliUtils.escapeSQLString(unescaped));
     }
-}
\ No newline at end of file
+}


Reply via email to