neo4j-core 5.1.14 → 6.0.0.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/neo4j-core.rb +1 -1
- data/lib/neo4j-core/helpers.rb +6 -0
- data/lib/neo4j-core/query.rb +88 -40
- data/lib/neo4j-core/query_clauses.rb +67 -67
- data/lib/neo4j-core/version.rb +1 -1
- data/lib/neo4j-embedded/embedded_label.rb +16 -14
- data/lib/neo4j-embedded/embedded_node.rb +115 -113
- data/lib/neo4j-embedded/embedded_relationship.rb +53 -51
- data/lib/neo4j-embedded/embedded_session.rb +5 -14
- data/lib/neo4j-embedded/label.rb +2 -1
- data/lib/neo4j-server/cypher_label.rb +8 -7
- data/lib/neo4j-server/cypher_relationship.rb +1 -1
- data/lib/neo4j-server/cypher_response.rb +3 -2
- data/lib/neo4j-server/cypher_transaction.rb +1 -6
- data/lib/neo4j-server/resource.rb +1 -1
- data/lib/neo4j/core/cypher_session.rb +28 -0
- data/lib/neo4j/core/cypher_session/adaptors.rb +108 -0
- data/lib/neo4j/core/cypher_session/adaptors/embedded.rb +81 -0
- data/lib/neo4j/core/cypher_session/adaptors/http.rb +159 -0
- data/lib/neo4j/core/cypher_session/responses.rb +27 -0
- data/lib/neo4j/core/cypher_session/responses/embedded.rb +77 -0
- data/lib/neo4j/core/cypher_session/responses/http.rb +104 -0
- data/lib/neo4j/core/cypher_session/result.rb +39 -0
- data/lib/neo4j/core/instrumentable.rb +36 -0
- data/lib/neo4j/core/node.rb +28 -0
- data/lib/neo4j/core/path.rb +15 -0
- data/lib/neo4j/core/relationship.rb +25 -0
- data/lib/neo4j/core/wrappable.rb +35 -0
- data/lib/neo4j/label.rb +7 -0
- data/lib/neo4j/session.rb +3 -3
- data/lib/neo4j/transaction.rb +1 -24
- data/neo4j-core.gemspec +2 -2
- metadata +22 -9
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d2e549ac9b629bd47019215c2457d66c6b355a2f
         | 
| 4 | 
            +
              data.tar.gz: 717fb2cc5363c0a7a9726ae4d686e504634d7310
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 14df3ab1fb20692a66036201039f66861b38fc340b3c63c7051d977b2a718c09a9daa3b5d717920ddaa5228089c899f8cf9f611c2e11e6cda992af6fc6d1838a
         | 
| 7 | 
            +
              data.tar.gz: ece61afe7b0c8c21db72322bfe5143ccc9ab7ef84dc6b01f7b7416b7978b28a082b0edb7dbc5587ed390cc9aa2da3555f4aad1fa11e96fb28e76e5de9d90e7c4
         | 
    
        data/lib/neo4j-core.rb
    CHANGED
    
    
    
        data/lib/neo4j-core/helpers.rb
    CHANGED
    
    
    
        data/lib/neo4j-core/query.rb
    CHANGED
    
    | @@ -18,16 +18,61 @@ module Neo4j | |
| 18 18 |  | 
| 19 19 | 
             
                  attr_accessor :clauses
         | 
| 20 20 |  | 
| 21 | 
            +
                  class Parameters
         | 
| 22 | 
            +
                    def initialize(hash = nil)
         | 
| 23 | 
            +
                      @parameters = (hash || {})
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    def to_hash
         | 
| 27 | 
            +
                      @parameters
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    def copy
         | 
| 31 | 
            +
                      self.class.new(@parameters.dup)
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    def add_param(key, value)
         | 
| 35 | 
            +
                      free_param_key(key).tap do |k|
         | 
| 36 | 
            +
                        @parameters[k.freeze] = value
         | 
| 37 | 
            +
                      end
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    def remove_param(key)
         | 
| 41 | 
            +
                      @parameters.delete(key.to_sym)
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    def add_params(params)
         | 
| 45 | 
            +
                      params.map do |key, value|
         | 
| 46 | 
            +
                        add_param(key, value)
         | 
| 47 | 
            +
                      end
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    private
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    def free_param_key(key)
         | 
| 53 | 
            +
                      k = key.to_sym
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                      return k if !@parameters.key?(k)
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                      i = 2
         | 
| 58 | 
            +
                      i += 1 while @parameters.key?("#{key}#{i}".to_sym)
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                      "#{key}#{i}".to_sym
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
             | 
| 21 64 | 
             
                  class << self
         | 
| 22 65 | 
             
                    attr_accessor :pretty_cypher
         | 
| 23 66 | 
             
                  end
         | 
| 24 67 |  | 
| 25 68 | 
             
                  def initialize(options = {})
         | 
| 26 | 
            -
                    @session = options[:session] | 
| 69 | 
            +
                    @session = options[:session]
         | 
| 70 | 
            +
                    @session = Neo4j::Session.current if !options.key?(:session)
         | 
| 27 71 |  | 
| 28 72 | 
             
                    @options = options
         | 
| 29 73 | 
             
                    @clauses = []
         | 
| 30 74 | 
             
                    @_params = {}
         | 
| 75 | 
            +
                    @params = Parameters.new
         | 
| 31 76 | 
             
                  end
         | 
| 32 77 |  | 
| 33 78 | 
             
                  def inspect
         | 
| @@ -113,9 +158,7 @@ module Neo4j | |
| 113 158 | 
             
                  METHODS = %w(start match optional_match using where create create_unique merge set on_create_set on_match_set remove unwind delete with return order skip limit)
         | 
| 114 159 | 
             
                  BREAK_METHODS = %(with)
         | 
| 115 160 |  | 
| 116 | 
            -
                  CLAUSIFY_CLAUSE = proc  | 
| 117 | 
            -
                    const_get(method.to_s.split('_').map(&:capitalize).join + 'Clause')
         | 
| 118 | 
            -
                  end
         | 
| 161 | 
            +
                  CLAUSIFY_CLAUSE = proc { |method| const_get(method.to_s.split('_').map(&:capitalize).join + 'Clause') }
         | 
| 119 162 |  | 
| 120 163 | 
             
                  CLAUSES = METHODS.map(&CLAUSIFY_CLAUSE)
         | 
| 121 164 |  | 
| @@ -171,9 +214,7 @@ module Neo4j | |
| 171 214 | 
             
                  #   Query.new.match('(q: Person {id: {id}})').params(id: 12)
         | 
| 172 215 | 
             
                  #
         | 
| 173 216 | 
             
                  def params(args)
         | 
| 174 | 
            -
                     | 
| 175 | 
            -
             | 
| 176 | 
            -
                    self
         | 
| 217 | 
            +
                    copy.tap { |new_query| new_query.instance_variable_get('@params').add_params(args) }
         | 
| 177 218 | 
             
                  end
         | 
| 178 219 |  | 
| 179 220 | 
             
                  def unwrapped
         | 
| @@ -187,25 +228,19 @@ module Neo4j | |
| 187 228 |  | 
| 188 229 | 
             
                  def response
         | 
| 189 230 | 
             
                    return @response if @response
         | 
| 231 | 
            +
             | 
| 190 232 | 
             
                    cypher = to_cypher
         | 
| 191 233 | 
             
                    pretty_cypher = to_cypher(pretty: true) if self.class.pretty_cypher
         | 
| 192 234 |  | 
| 193 235 | 
             
                    @response = @session._query(cypher, merge_params, context: @options[:context], pretty_cypher: pretty_cypher)
         | 
| 194 236 |  | 
| 195 | 
            -
                     | 
| 196 | 
            -
                      response
         | 
| 197 | 
            -
                    else
         | 
| 198 | 
            -
                      response.raise_cypher_error
         | 
| 199 | 
            -
                    end
         | 
| 237 | 
            +
                    (!response.respond_to?(:error?) || !response.error?) ? response : response.raise_cypher_error
         | 
| 200 238 | 
             
                  end
         | 
| 201 239 |  | 
| 202 240 | 
             
                  def match_nodes(hash, optional_match = false)
         | 
| 203 241 | 
             
                    hash.inject(self) do |query, (variable, node_object)|
         | 
| 204 | 
            -
                      neo_id =  | 
| 205 | 
            -
             | 
| 206 | 
            -
                               else
         | 
| 207 | 
            -
                                 node_object
         | 
| 208 | 
            -
                               end
         | 
| 242 | 
            +
                      neo_id = (node_object.respond_to?(:neo_id) ? node_object.neo_id : node_object)
         | 
| 243 | 
            +
             | 
| 209 244 | 
             
                      match_method = optional_match ? :optional_match : :match
         | 
| 210 245 | 
             
                      query.send(match_method, variable).where(variable => {neo_id: neo_id})
         | 
| 211 246 | 
             
                    end
         | 
| @@ -267,11 +302,7 @@ module Neo4j | |
| 267 302 | 
             
                      column = columns[0]
         | 
| 268 303 | 
             
                      query.map { |row| row[column] }
         | 
| 269 304 | 
             
                    else
         | 
| 270 | 
            -
                      query.map  | 
| 271 | 
            -
                        columns.map do |column|
         | 
| 272 | 
            -
                          row[column]
         | 
| 273 | 
            -
                        end
         | 
| 274 | 
            -
                      end
         | 
| 305 | 
            +
                      query.map { |row| columns.map { |column| row[column] } }
         | 
| 275 306 | 
             
                    end
         | 
| 276 307 | 
             
                  end
         | 
| 277 308 |  | 
| @@ -290,20 +321,39 @@ module Neo4j | |
| 290 321 | 
             
                  EMPTY = ' '
         | 
| 291 322 | 
             
                  NEWLINE = "\n"
         | 
| 292 323 | 
             
                  def to_cypher(options = {})
         | 
| 293 | 
            -
                     | 
| 324 | 
            +
                    join_string = options[:pretty] ? NEWLINE : EMPTY
         | 
| 325 | 
            +
             | 
| 326 | 
            +
                    cypher_string = partitioned_clauses.map do |clauses|
         | 
| 294 327 | 
             
                      clauses_by_class = clauses.group_by(&:class)
         | 
| 295 328 |  | 
| 296 329 | 
             
                      cypher_parts = CLAUSES.map do |clause_class|
         | 
| 297 | 
            -
                        clause_class.to_cypher(clauses, options) if clauses = clauses_by_class[clause_class]
         | 
| 298 | 
            -
                      end
         | 
| 330 | 
            +
                        clause_class.to_cypher(clauses, options[:pretty]) if clauses = clauses_by_class[clause_class]
         | 
| 331 | 
            +
                      end.compact
         | 
| 299 332 |  | 
| 300 | 
            -
                      cypher_parts. | 
| 301 | 
            -
             | 
| 302 | 
            -
                    end.join(options[:pretty] ? NEWLINE : EMPTY)
         | 
| 333 | 
            +
                      cypher_parts.join(join_string).tap(&:strip!)
         | 
| 334 | 
            +
                    end.join(join_string)
         | 
| 303 335 |  | 
| 304 336 | 
             
                    cypher_string = "CYPHER #{@options[:parser]} #{cypher_string}" if @options[:parser]
         | 
| 305 337 | 
             
                    cypher_string.tap(&:strip!)
         | 
| 306 338 | 
             
                  end
         | 
| 339 | 
            +
                  alias_method :cypher, :to_cypher
         | 
| 340 | 
            +
             | 
| 341 | 
            +
                  def pretty_cypher
         | 
| 342 | 
            +
                    to_cypher(pretty: true)
         | 
| 343 | 
            +
                  end
         | 
| 344 | 
            +
             | 
| 345 | 
            +
                  def context
         | 
| 346 | 
            +
                    @options[:context]
         | 
| 347 | 
            +
                  end
         | 
| 348 | 
            +
             | 
| 349 | 
            +
                  def parameters
         | 
| 350 | 
            +
                    to_cypher
         | 
| 351 | 
            +
                    merge_params
         | 
| 352 | 
            +
                  end
         | 
| 353 | 
            +
             | 
| 354 | 
            +
                  def partitioned_clauses
         | 
| 355 | 
            +
                    @partitioned_clauses ||= PartitionedClauses.new(@clauses)
         | 
| 356 | 
            +
                  end
         | 
| 307 357 |  | 
| 308 358 | 
             
                  def print_cypher
         | 
| 309 359 | 
             
                    puts to_cypher(pretty: true).gsub(/\e[^m]+m/, '')
         | 
| @@ -332,20 +382,18 @@ module Neo4j | |
| 332 382 | 
             
                    end.params(other._params)
         | 
| 333 383 | 
             
                  end
         | 
| 334 384 |  | 
| 335 | 
            -
                  MEMOIZED_INSTANCE_VARIABLES = [:response, :merge_params]
         | 
| 336 385 | 
             
                  def copy
         | 
| 337 386 | 
             
                    dup.tap do |query|
         | 
| 338 | 
            -
                       | 
| 339 | 
            -
             | 
| 340 | 
            -
                       | 
| 387 | 
            +
                      to_cypher
         | 
| 388 | 
            +
                      query.instance_variable_set('@params', @params.copy)
         | 
| 389 | 
            +
                      query.instance_variable_set('@partitioned_clauses', nil)
         | 
| 390 | 
            +
                      query.instance_variable_set('@response', nil)
         | 
| 341 391 | 
             
                    end
         | 
| 342 392 | 
             
                  end
         | 
| 343 393 |  | 
| 344 394 | 
             
                  def clause?(method)
         | 
| 345 395 | 
             
                    clause_class = DEFINED_CLAUSES[method] || CLAUSIFY_CLAUSE.call(method)
         | 
| 346 | 
            -
                    clauses.any?  | 
| 347 | 
            -
                      clause.is_a?(clause_class)
         | 
| 348 | 
            -
                    end
         | 
| 396 | 
            +
                    clauses.any? { |clause| clause.is_a?(clause_class) }
         | 
| 349 397 | 
             
                  end
         | 
| 350 398 |  | 
| 351 399 | 
             
                  protected
         | 
| @@ -357,9 +405,7 @@ module Neo4j | |
| 357 405 | 
             
                  end
         | 
| 358 406 |  | 
| 359 407 | 
             
                  def remove_clause_class(clause_class)
         | 
| 360 | 
            -
                    @clauses = @clauses.reject  | 
| 361 | 
            -
                      clause.is_a?(clause_class)
         | 
| 362 | 
            -
                    end
         | 
| 408 | 
            +
                    @clauses = @clauses.reject { |clause| clause.is_a?(clause_class) }
         | 
| 363 409 | 
             
                  end
         | 
| 364 410 |  | 
| 365 411 | 
             
                  private
         | 
| @@ -367,7 +413,7 @@ module Neo4j | |
| 367 413 | 
             
                  def build_deeper_query(clause_class, args = {}, options = {})
         | 
| 368 414 | 
             
                    copy.tap do |new_query|
         | 
| 369 415 | 
             
                      new_query.add_clauses [nil] if [nil, WithClause].include?(clause_class)
         | 
| 370 | 
            -
                      new_query.add_clauses clause_class.from_args(args, options) if clause_class
         | 
| 416 | 
            +
                      new_query.add_clauses clause_class.from_args(args, new_query.instance_variable_get('@params'), options) if clause_class
         | 
| 371 417 | 
             
                    end
         | 
| 372 418 | 
             
                  end
         | 
| 373 419 |  | 
| @@ -430,9 +476,11 @@ module Neo4j | |
| 430 476 | 
             
                    end
         | 
| 431 477 | 
             
                  end
         | 
| 432 478 |  | 
| 479 | 
            +
                  # SHOULD BE DEPRECATED
         | 
| 433 480 | 
             
                  def merge_params
         | 
| 434 481 | 
             
                    @clauses.compact!
         | 
| 435 | 
            -
                    @merge_params ||= @clauses.inject(@ | 
| 482 | 
            +
                    @merge_params ||= @clauses.inject(@params.to_hash) { |params, clause| params.merge!(clause.params) }
         | 
| 483 | 
            +
                    @params.to_hash
         | 
| 436 484 | 
             
                  end
         | 
| 437 485 | 
             
                end
         | 
| 438 486 | 
             
              end
         | 
| @@ -9,25 +9,27 @@ module Neo4j | |
| 9 9 | 
             
                    end
         | 
| 10 10 | 
             
                  end
         | 
| 11 11 |  | 
| 12 | 
            -
             | 
| 13 12 | 
             
                  class Clause
         | 
| 14 13 | 
             
                    UNDERSCORE = '_'
         | 
| 15 14 | 
             
                    COMMA_SPACE = ', '
         | 
| 16 15 | 
             
                    AND = ' AND '
         | 
| 17 16 |  | 
| 18 17 | 
             
                    attr_accessor :params, :arg
         | 
| 19 | 
            -
                    attr_reader :options
         | 
| 18 | 
            +
                    attr_reader :options, :param_vars_added
         | 
| 20 19 |  | 
| 21 | 
            -
                    def initialize(arg, options = {})
         | 
| 20 | 
            +
                    def initialize(arg, params, options = {})
         | 
| 22 21 | 
             
                      @arg = arg
         | 
| 23 22 | 
             
                      @options = options
         | 
| 24 | 
            -
                      @params =  | 
| 23 | 
            +
                      @params = params
         | 
| 24 | 
            +
                      @param_vars_added = []
         | 
| 25 25 | 
             
                    end
         | 
| 26 26 |  | 
| 27 27 | 
             
                    def value
         | 
| 28 | 
            +
                      return @value if @value
         | 
| 29 | 
            +
             | 
| 28 30 | 
             
                      [String, Symbol, Integer, Hash, NilClass].each do |arg_class|
         | 
| 29 31 | 
             
                        from_method = "from_#{arg_class.name.downcase}"
         | 
| 30 | 
            -
                        return send(from_method, @arg) if @arg.is_a?(arg_class) && self.respond_to?(from_method)
         | 
| 32 | 
            +
                        return @value = send(from_method, @arg) if @arg.is_a?(arg_class) && self.respond_to?(from_method)
         | 
| 31 33 | 
             
                      end
         | 
| 32 34 |  | 
| 33 35 | 
             
                      fail ArgError
         | 
| @@ -124,21 +126,19 @@ module Neo4j | |
| 124 126 | 
             
                        keyword.downcase
         | 
| 125 127 | 
             
                      end
         | 
| 126 128 |  | 
| 127 | 
            -
                      def from_args(args, options = {})
         | 
| 129 | 
            +
                      def from_args(args, params, options = {})
         | 
| 128 130 | 
             
                        args.flatten!
         | 
| 129 | 
            -
                        args.map { |arg| from_arg(arg, options) }.tap(&:compact!)
         | 
| 131 | 
            +
                        args.map { |arg| from_arg(arg, params, options) }.tap(&:compact!)
         | 
| 130 132 | 
             
                      end
         | 
| 131 133 |  | 
| 132 | 
            -
                      def from_arg(arg, options = {})
         | 
| 133 | 
            -
                        new(arg, options) if !arg.respond_to?(:empty?) || !arg.empty?
         | 
| 134 | 
            +
                      def from_arg(arg, params, options = {})
         | 
| 135 | 
            +
                        new(arg, params, options) if !arg.respond_to?(:empty?) || !arg.empty?
         | 
| 134 136 | 
             
                      end
         | 
| 135 137 |  | 
| 136 | 
            -
                      def to_cypher(clauses,  | 
| 137 | 
            -
                         | 
| 138 | 
            -
             | 
| 139 | 
            -
                        string = clause_string(clauses, options)
         | 
| 138 | 
            +
                      def to_cypher(clauses, pretty = false)
         | 
| 139 | 
            +
                        string = clause_string(clauses, pretty)
         | 
| 140 140 |  | 
| 141 | 
            -
                        final_keyword = if  | 
| 141 | 
            +
                        final_keyword = if pretty
         | 
| 142 142 | 
             
                                          "#{clause_color}#{keyword}#{ANSI::CLEAR}"
         | 
| 143 143 | 
             
                                        else
         | 
| 144 144 | 
             
                                          keyword
         | 
| @@ -147,11 +147,11 @@ module Neo4j | |
| 147 147 | 
             
                        "#{final_keyword} #{string}" if string.size > 0
         | 
| 148 148 | 
             
                      end
         | 
| 149 149 |  | 
| 150 | 
            -
                      def clause_string(clauses,  | 
| 151 | 
            -
                        join_string = clause_join + ( | 
| 150 | 
            +
                      def clause_string(clauses, pretty)
         | 
| 151 | 
            +
                        join_string = clause_join + (pretty ? "\n  " : '')
         | 
| 152 152 |  | 
| 153 153 | 
             
                        strings = clause_strings(clauses)
         | 
| 154 | 
            -
                        string = (( | 
| 154 | 
            +
                        string = ((pretty && strings.size > 1) ? "\n  " : '')
         | 
| 155 155 | 
             
                        string + strings.join(join_string).strip
         | 
| 156 156 | 
             
                      end
         | 
| 157 157 |  | 
| @@ -169,6 +169,16 @@ module Neo4j | |
| 169 169 | 
             
                      key.gsub!(/^_+|_+$/, '')
         | 
| 170 170 | 
             
                    end
         | 
| 171 171 |  | 
| 172 | 
            +
                    def add_param(key, value)
         | 
| 173 | 
            +
                      @param_vars_added << key
         | 
| 174 | 
            +
                      @params.add_param(key, value)
         | 
| 175 | 
            +
                    end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                    def add_params(keys_and_values)
         | 
| 178 | 
            +
                      @param_vars_added += keys_and_values.keys
         | 
| 179 | 
            +
                      @params.add_params(keys_and_values)
         | 
| 180 | 
            +
                    end
         | 
| 181 | 
            +
             | 
| 172 182 | 
             
                    private
         | 
| 173 183 |  | 
| 174 184 | 
             
                    def key_value_string(key, value, previous_keys = [], is_set = false)
         | 
| @@ -176,14 +186,14 @@ module Neo4j | |
| 176 186 | 
             
                      self.class.paramaterize_key!(param)
         | 
| 177 187 |  | 
| 178 188 | 
             
                      if value.is_a?(Range)
         | 
| 179 | 
            -
                        add_params("#{param}_range_min" => value.min, "#{param}_range_max" => value.max)
         | 
| 189 | 
            +
                        min_param, max_param = add_params("#{param}_range_min" => value.min, "#{param}_range_max" => value.max)
         | 
| 180 190 |  | 
| 181 | 
            -
                        "#{key} IN RANGE({#{ | 
| 191 | 
            +
                        "#{key} IN RANGE({#{min_param}}, {#{max_param}})"
         | 
| 182 192 | 
             
                      else
         | 
| 183 193 | 
             
                        value = value.first if array_value?(value, is_set) && value.size == 1
         | 
| 184 194 | 
             
                        operator = array_value?(value, is_set) ? 'IN' : '='
         | 
| 185 195 |  | 
| 186 | 
            -
                        add_param(param, value)
         | 
| 196 | 
            +
                        param = add_param(param, value)
         | 
| 187 197 |  | 
| 188 198 | 
             
                        "#{key} #{operator} {#{param}}"
         | 
| 189 199 | 
             
                      end
         | 
| @@ -193,16 +203,6 @@ module Neo4j | |
| 193 203 | 
             
                      value.is_a?(Array) && !is_set
         | 
| 194 204 | 
             
                    end
         | 
| 195 205 |  | 
| 196 | 
            -
                    def add_param(key, value)
         | 
| 197 | 
            -
                      @params[key.freeze.to_sym] = value
         | 
| 198 | 
            -
                    end
         | 
| 199 | 
            -
             | 
| 200 | 
            -
                    def add_params(params)
         | 
| 201 | 
            -
                      params.each do |key, value|
         | 
| 202 | 
            -
                        add_param(key, value)
         | 
| 203 | 
            -
                      end
         | 
| 204 | 
            -
                    end
         | 
| 205 | 
            -
             | 
| 206 206 | 
             
                    def format_label(label_arg)
         | 
| 207 207 | 
             
                      if label_arg.is_a?(Array)
         | 
| 208 208 | 
             
                        return label_arg.map { |arg| format_label(arg) }.join
         | 
| @@ -225,7 +225,7 @@ module Neo4j | |
| 225 225 | 
             
                          "#{key}: #{value}"
         | 
| 226 226 | 
             
                        else
         | 
| 227 227 | 
             
                          param_key = "#{prefix}#{key}".gsub('::', '_')
         | 
| 228 | 
            -
                          add_param(param_key, value)
         | 
| 228 | 
            +
                          param_key = add_param(param_key, value)
         | 
| 229 229 | 
             
                          "#{key}: {#{param_key}}"
         | 
| 230 230 | 
             
                        end
         | 
| 231 231 | 
             
                      end.join(Clause::COMMA_SPACE)
         | 
| @@ -310,7 +310,7 @@ module Neo4j | |
| 310 310 | 
             
                      param = [previous_keys + [key]].join(UNDERSCORE)
         | 
| 311 311 | 
             
                      self.class.paramaterize_key!(param)
         | 
| 312 312 |  | 
| 313 | 
            -
                       | 
| 313 | 
            +
                      param = add_param(param, pattern)
         | 
| 314 314 |  | 
| 315 315 | 
             
                      "#{key} =~ {#{param}}"
         | 
| 316 316 | 
             
                    end
         | 
| @@ -318,36 +318,22 @@ module Neo4j | |
| 318 318 | 
             
                    class << self
         | 
| 319 319 | 
             
                      ARG_HAS_QUESTION_MARK_REGEX = /(^|\(|\s)\?(\s|\)|$)/
         | 
| 320 320 |  | 
| 321 | 
            -
                      def from_args(args, options = {})
         | 
| 322 | 
            -
                        query_string,  | 
| 323 | 
            -
             | 
| 324 | 
            -
                        if query_string.is_a?(String) && (query_string.match(ARG_HAS_QUESTION_MARK_REGEX) || params.is_a?(Hash))
         | 
| 325 | 
            -
                          if !params.is_a?(Hash)
         | 
| 326 | 
            -
                            question_mark_params_param = self.question_mark_params_param
         | 
| 327 | 
            -
                            query_string = query_string.gsub(ARG_HAS_QUESTION_MARK_REGEX, "\\1{#{question_mark_params_param}}\\2")
         | 
| 328 | 
            -
                            params = {question_mark_params_param.to_sym => params}
         | 
| 329 | 
            -
                          end
         | 
| 321 | 
            +
                      def from_args(args, params, options = {})
         | 
| 322 | 
            +
                        query_string, params_arg = args
         | 
| 330 323 |  | 
| 331 | 
            -
             | 
| 332 | 
            -
             | 
| 324 | 
            +
                        if query_string.is_a?(String) && (query_string.match(ARG_HAS_QUESTION_MARK_REGEX) || params_arg.is_a?(Hash))
         | 
| 325 | 
            +
                          if params_arg.is_a?(Hash)
         | 
| 326 | 
            +
                            params.add_params(params_arg)
         | 
| 327 | 
            +
                          else
         | 
| 328 | 
            +
                            param_var = params.add_params(question_mark_param: params_arg)[0]
         | 
| 329 | 
            +
                            query_string = query_string.gsub(ARG_HAS_QUESTION_MARK_REGEX, "\\1{#{param_var}}\\2")
         | 
| 333 330 | 
             
                          end
         | 
| 334 331 |  | 
| 335 | 
            -
                          [ | 
| 332 | 
            +
                          [from_arg(query_string, params, options)]
         | 
| 336 333 | 
             
                        else
         | 
| 337 334 | 
             
                          super
         | 
| 338 335 | 
             
                        end
         | 
| 339 336 | 
             
                      end
         | 
| 340 | 
            -
             | 
| 341 | 
            -
                      def question_mark_params_param
         | 
| 342 | 
            -
                        "question_mark_param#{question_mark_param_index}"
         | 
| 343 | 
            -
                      end
         | 
| 344 | 
            -
             | 
| 345 | 
            -
                      def question_mark_param_index
         | 
| 346 | 
            -
                        @question_mark_param_index ||= 1
         | 
| 347 | 
            -
                        @question_mark_param_index.tap do
         | 
| 348 | 
            -
                          @question_mark_param_index += 1
         | 
| 349 | 
            -
                        end
         | 
| 350 | 
            -
                      end
         | 
| 351 337 | 
             
                    end
         | 
| 352 338 | 
             
                  end
         | 
| 353 339 |  | 
| @@ -464,6 +450,10 @@ module Neo4j | |
| 464 450 | 
             
                      def clause_color
         | 
| 465 451 | 
             
                        ANSI::MAGENTA
         | 
| 466 452 | 
             
                      end
         | 
| 453 | 
            +
             | 
| 454 | 
            +
                      def clause_join
         | 
| 455 | 
            +
                        ' MERGE '
         | 
| 456 | 
            +
                      end
         | 
| 467 457 | 
             
                    end
         | 
| 468 458 | 
             
                  end
         | 
| 469 459 |  | 
| @@ -524,15 +514,13 @@ module Neo4j | |
| 524 514 | 
             
                    KEYWORD = 'LIMIT'
         | 
| 525 515 |  | 
| 526 516 | 
             
                    def from_string(value)
         | 
| 527 | 
            -
                       | 
| 528 | 
            -
                      add_param( | 
| 529 | 
            -
                      "{#{ | 
| 517 | 
            +
                      param_var = "#{self.class.keyword_downcase}_#{value}"
         | 
| 518 | 
            +
                      param_var = add_param(param_var, value.to_i)
         | 
| 519 | 
            +
                      "{#{param_var}}"
         | 
| 530 520 | 
             
                    end
         | 
| 531 521 |  | 
| 532 522 | 
             
                    def from_integer(value)
         | 
| 533 | 
            -
                       | 
| 534 | 
            -
                      add_param(clause_id, value)
         | 
| 535 | 
            -
                      "{#{clause_id}}"
         | 
| 523 | 
            +
                      from_string(value)
         | 
| 536 524 | 
             
                    end
         | 
| 537 525 |  | 
| 538 526 | 
             
                    def from_nilclass(value)
         | 
| @@ -541,7 +529,13 @@ module Neo4j | |
| 541 529 |  | 
| 542 530 | 
             
                    class << self
         | 
| 543 531 | 
             
                      def clause_strings(clauses)
         | 
| 544 | 
            -
                         | 
| 532 | 
            +
                        result_clause = clauses.last
         | 
| 533 | 
            +
             | 
| 534 | 
            +
                        clauses[0..-2].map(&:param_vars_added).flatten.grep(/^limit_\d+$/).each do |var|
         | 
| 535 | 
            +
                          result_clause.params.remove_param(var)
         | 
| 536 | 
            +
                        end
         | 
| 537 | 
            +
             | 
| 538 | 
            +
                        [result_clause.value]
         | 
| 545 539 | 
             
                      end
         | 
| 546 540 | 
             
                    end
         | 
| 547 541 | 
             
                  end
         | 
| @@ -551,19 +545,25 @@ module Neo4j | |
| 551 545 |  | 
| 552 546 | 
             
                    def from_string(value)
         | 
| 553 547 | 
             
                      clause_id = "#{self.class.keyword_downcase}_#{value}"
         | 
| 554 | 
            -
                      add_param(clause_id, value.to_i)
         | 
| 548 | 
            +
                      clause_id = add_param(clause_id, value.to_i)
         | 
| 555 549 | 
             
                      "{#{clause_id}}"
         | 
| 556 550 | 
             
                    end
         | 
| 557 551 |  | 
| 558 552 | 
             
                    def from_integer(value)
         | 
| 559 553 | 
             
                      clause_id = "#{self.class.keyword_downcase}_#{value}"
         | 
| 560 | 
            -
                      add_param(clause_id, value)
         | 
| 554 | 
            +
                      clause_id = add_param(clause_id, value)
         | 
| 561 555 | 
             
                      "{#{clause_id}}"
         | 
| 562 556 | 
             
                    end
         | 
| 563 557 |  | 
| 564 558 | 
             
                    class << self
         | 
| 565 559 | 
             
                      def clause_strings(clauses)
         | 
| 566 | 
            -
                         | 
| 560 | 
            +
                        result_clause = clauses.last
         | 
| 561 | 
            +
             | 
| 562 | 
            +
                        clauses[0..-2].map(&:param_vars_added).flatten.grep(/^skip_\d+$/).each do |var|
         | 
| 563 | 
            +
                          result_clause.params.remove_param(var)
         | 
| 564 | 
            +
                        end
         | 
| 565 | 
            +
             | 
| 566 | 
            +
                        [result_clause.value]
         | 
| 567 567 | 
             
                      end
         | 
| 568 568 | 
             
                    end
         | 
| 569 569 | 
             
                  end
         | 
| @@ -576,8 +576,8 @@ module Neo4j | |
| 576 576 | 
             
                      when String, Symbol then "#{key}:`#{value}`"
         | 
| 577 577 | 
             
                      when Hash
         | 
| 578 578 | 
             
                        if @options[:set_props]
         | 
| 579 | 
            -
                          add_param("#{key}_set_props", value)
         | 
| 580 | 
            -
                          "#{key} = {#{ | 
| 579 | 
            +
                          param = add_param("#{key}_set_props", value)
         | 
| 580 | 
            +
                          "#{key} = {#{param}}"
         | 
| 581 581 | 
             
                        else
         | 
| 582 582 | 
             
                          value.map { |k, v| key_value_string("#{key}.`#{k}`", v, ['setter'], true) }
         | 
| 583 583 | 
             
                        end
         |