Repository: gluesql/gluesql
Pull request #120 (2020-11-23 14:36:28)

INSERT INTO SELECT
Working :-)

Relates to #119


Patch:
diff --git a/src/executor/execute.rs b/src/executor/execute.rs
index 35fdae75..a64dc2d2 100644
--- a/src/executor/execute.rs
+++ b/src/executor/execute.rs
@@ -15,7 +15,7 @@ use crate::store::{AlterTable, Store, StoreMut};
 
 use super::fetch::{fetch, fetch_columns};
 use super::filter::Filter;
-use super::select::select_with_labels;
+use super::select::{select, select_with_labels};
 use super::update::Update;
 
 #[derive(ThisError, Serialize, Debug, PartialEq)]
@@ -27,7 +27,7 @@ pub enum ExecuteError {
     DropTypeNotSupported,
 
     #[error("unsupported insert value type: {0}")]
-    UnsupportedInsertValueType(String),
+    UnreachableUnsupportedInsertValueType(String),
 
     #[cfg(feature = "alter-table")]
     #[error("unsupported alter table operation: {0}")]
@@ -241,20 +241,36 @@ async fn prepare<'a, T: 'static + Debug>(
                 .await?
                 .ok_or(ExecuteError::TableNotExists)?;
 
-            let values_list = match &source.body {
-                SetExpr::Values(Values(values_list)) => values_list,
+            let rows = match &source.body {
+                SetExpr::Values(Values(values_list)) => values_list
+                    .iter()
+                    .map(|values| Row::new(&column_defs, columns, values))
+                    .collect::<Result<_>>()?,
+                SetExpr::Select(select_query) => {
+                    select(
+                        storage,
+                        &sqlparser::ast::Query {
+                            ctes: vec![],
+                            body: SetExpr::Select(select_query.clone()),
+                            order_by: vec![],
+                            limit: None,
+                            offset: None,
+                            fetch: None,
+                        },
+                        None,
+                    )
+                    .await?
+                    .try_collect::<Vec<_>>()
+                    .await?
+                }
                 set_expr => {
-                    return Err(
-                        ExecuteError::UnsupportedInsertValueType(set_expr.to_string()).into(),
-                    );
+                    return Err(ExecuteError::UnreachableUnsupportedInsertValueType(
+                        set_expr.to_string(),
+                    )
+                    .into());
                 }
             };
 
-            let rows = values_list
-                .iter()
-                .map(|values| Row::new(&column_defs, columns, values))
-                .collect::<Result<_>>()?;
-
             Ok(Prepared::Insert(table_name, rows))
         }
         Statement::Update {


Test patch:
diff --git a/src/tests/basic.rs b/src/tests/basic.rs
index 6409a28c..c391b467 100644
--- a/src/tests/basic.rs
+++ b/src/tests/basic.rs
@@ -7,11 +7,20 @@ CREATE TABLE Test (
     id INTEGER,
     num INTEGER,
     name TEXT
+)"#
+    );
+    run!(
+        r#"
+CREATE TABLE TestA (
+    id INTEGER,
+    num INTEGER,
+    name TEXT
 )"#
     );
     run!("INSERT INTO Test (id, num, name) VALUES (1, 2, \"Hello\")");
     run!("INSERT INTO Test (id, num, name) VALUES (1, 9, \"World\")");
     run!("INSERT INTO Test (id, num, name) VALUES (3, 4, \"Great\"), (4, 7, \"Job\")");
+    run!("INSERT INTO TestA (id, num, name) SELECT id, num, name FROM Test");
 
     use Value::*;
 
@@ -27,6 +36,18 @@ CREATE TABLE Test (
         "SELECT id, num, name FROM Test"
     );
 
+    test!(
+        Ok(select!(
+            id  | num | name
+            I64 | I64 | Str;
+            1     2     "Hello".to_owned();
+            1     9     "World".to_owned();
+            3     4     "Great".to_owned();
+            4     7     "Job".to_owned()
+        )),
+        "SELECT id, num, name FROM TestA"
+    );
+
     count!(4, "SELECT * FROM Test");
 
     run!("UPDATE Test SET id = 2");
diff --git a/src/tests/error.rs b/src/tests/error.rs
index 4362f909..3d854339 100644
--- a/src/tests/error.rs
+++ b/src/tests/error.rs
@@ -46,10 +46,6 @@ test_case!(error, async move {
             RowError::TooManyValues.into(),
             "INSERT INTO TableA VALUES (100), (100, 200);",
         ),
-        (
-            ExecuteError::UnsupportedInsertValueType("SELECT id FROM TableA".to_owned()).into(),
-            "INSERT INTO TableA SELECT id FROM TableA",
-        ),
         #[cfg(feature = "alter-table")]
         (
             ExecuteError::UnsupportedAlterTableOperation(