@@ -419,13 +419,13 @@ defmodule Ecto.Adapters.MyXQL do
419419 case File . read ( path ) do
420420 { :ok , contents } ->
421421 args = [
422- "--execute " ,
423- "SET FOREIGN_KEY_CHECKS = 0; " <> contents <> "; SET FOREIGN_KEY_CHECKS = 1 ",
422+ "--init-command " ,
423+ "SET FOREIGN_KEY_CHECKS = 0;" ,
424424 "--database" ,
425425 config [ :database ]
426426 ]
427427
428- case run_with_cmd ( "mysql" , config , args ) do
428+ case run_with_port ( "mysql" , config , args , contents ) do
429429 { _output , 0 } -> { :ok , path }
430430 { output , _ } -> { :error , output }
431431 end
@@ -497,6 +497,12 @@ defmodule Ecto.Adapters.MyXQL do
497497 "please guarantee it is available before running ecto commands"
498498 end
499499
500+ { args , cmd_opts } = args_cmd_opts ( opts , opt_args , cmd_opts )
501+
502+ System . cmd ( cmd , args , cmd_opts )
503+ end
504+
505+ defp args_cmd_opts ( opts , opt_args , cmd_opts ) do
500506 env =
501507 if password = opts [ :password ] do
502508 [ { "MYSQL_PWD" , password } ]
@@ -530,6 +536,77 @@ defmodule Ecto.Adapters.MyXQL do
530536 |> Keyword . put_new ( :stderr_to_stdout , true )
531537 |> Keyword . update ( :env , env , & Enum . concat ( env , & 1 ) )
532538
533- System . cmd ( cmd , args , cmd_opts )
539+ { args , cmd_opts }
540+ end
541+
542+ // Largely ported from Elixir System. cmd implementation
543+ // with the intent of using file redirection for passing
544+ // dump files into the mysql client so that users don 't
545+ // run into shell limits when dump files are large
546+ defp run_with_port(cmd, opts, opt_args, contents, cmd_opts \\ []) do
547+ unless System.find_executable(cmd) do
548+ raise "could not find executable `#{ cmd } ` in path, " <>
549+ "please guarantee it is available before running ecto commands"
550+ end
551+
552+ {args, cmd_opts} = args_cmd_opts(opts, opt_args, cmd_opts)
553+
554+ cmd =
555+ if Path.type(cmd) == :absolute do
556+ cmd
557+ else
558+ :os.find_executable(cmd) || :erlang.error(:enoent, [command, args, cmd_opts])
559+ end
560+
561+ port_opts = port_opts(cmd_opts, [args: args])
562+ port = Port.open({:spawn_executable, cmd}, port_opts)
563+ Port.command(port, content)
564+
565+ try do
566+ {initial, fun} = Collectable.into("")
567+ do_port_byte(port, initial, fun)
568+ catch
569+ kind, reason ->
570+ fun.(initial, :halt)
571+ :erlang.raise(kind, reason, __STACKTRACE__)
572+ else
573+ {acc, status} -> {fun.(acc, :done), status}
574+ end
575+ end
576+
577+ defp port_opts([{:stderr_to_stdout, true} | t], acc),
578+ do: port_opts(t, [:stderr_to_stdout | acc])
579+
580+ defp port_opts([{:stderr_to_stdout, _} | t], acc),
581+ do: port_opts(t, acc)
582+
583+ defp port_opts([{:env, enum} | t], acc),
584+ do: port_opts(t, [{:env, validate_env(enum)} | acc])
585+
586+ defp port_opts([], acc) do
587+ [:use_stdio, :exit_status, :binary, :hide] ++ acc
588+ end
589+
590+ defp validate_env(enum) do
591+ Enum.map(enum, fn
592+ {k, nil} ->
593+ {String.to_charlist(k), false}
594+
595+ {k, v} ->
596+ {String.to_charlist(k), String.to_charlist(v)}
597+
598+ other ->
599+ raise ArgumentError, "invalid environment key-value #{ inspect ( other ) } "
600+ end)
601+ end
602+
603+ defp do_port_byte(port, acc, fun) do
604+ receive do
605+ {^port, {:data, data}} ->
606+ do_port_byte(port, fun.(acc, {:cont, data}), fun)
607+
608+ {^port, {:exit_status, status}} ->
609+ {acc, status}
610+ end
534611 end
535612end
0 commit comments