# File lib/flexirecord.rb, line 1266
1266:     def record_query(record_class, command_template, *command_arguments)
1267:       command = command_template.to_s.gsub(/\$([^0-9]|$)/) {
1268:         if command_arguments.empty?
1269:           raise ArgumentError, "Too few arguments supplied for SQL command."
1270:         end
1271:         command_argument = command_arguments.shift
1272:         if command_argument.kind_of? Rational
1273:           command_argument = command_argument.to_f
1274:         elsif command_argument.kind_of? Time
1275:           time_offset_hours = command_argument.utc_offset / 3600
1276:           unless 3600 * time_offset_hours == command_argument.utc_offset
1277:             raise "Time zone offset is not an integer amount of hours."
1278:           end
1279:           command_argument = "%s.%06i%+03i" % [command_argument.strftime("%Y-%m-%d %H:%M:%S"), command_argument.usec, time_offset_hours]
1280:         end
1281:         PGconn.quote(command_argument) << $1
1282:         # argument = command_arguments.shift
1283:         # if argument.kind_of? FlexiRecord::SqlSnippet
1284:         #   argument.to_s + $1
1285:         # else
1286:         #   PGconn.quote(argument) << $1
1287:         # end
1288:       }
1289:       raise ArgumentError, "Too many arguments supplied for SQL command." unless command_arguments.empty?
1290:       if $flexirecord_debug_output
1291:         $flexirecord_debug_output << "#{command}\n"
1292:       end
1293:       begin
1294:         synchronize do
1295:           if record_class
1296:             backend_result = @backend_connection.async_exec(command)
1297:             result = FlexiRecord::RecordArray.new(record_class)
1298:             for row in 0...(backend_result.num_tuples)
1299:               record_data = {}
1300:               for col in 0...(backend_result.num_fields)
1301:                 value_string = backend_result.getvalue(row, col)
1302:                 record_data[backend_result.fieldname(col)] = if value_string.nil?
1303:                   nil
1304:                 else
1305:                   if @data_types
1306:                     data_type = @data_types[backend_result.type(col)]
1307:                     if data_type == "bool"
1308:                       value_string[0, 1] == 't'
1309:                     elsif ["int2", "int4", "int8"].include? data_type
1310:                       value_string.to_i
1311:                     elsif ["text", "varchar"].include? data_type
1312:                       value_string
1313:                     elsif data_type == "numeric"
1314:                       unless value_string =~ /^([0-9]*)(\.([0-9]+)?)?$/
1315:                         raise "Unexpected format for numeric data from database."
1316:                       end
1317:                       if $3
1318:                         $1.to_i + Rational($3.to_i, 10**($3.length))
1319:                       else
1320:                         $1.to_i
1321:                       end
1322:                     elsif data_type == "date"
1323:                       unless value_string =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/
1324:                         raise "Unexpected format for date from database."
1325:                       end
1326:                       Time.local($1.to_i, $2.to_i, $3.to_i)
1327:                     elsif data_type == "timestamp"
1328:                       unless value_string =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]*))?$/
1329:                         raise "Unexpected format for timestamp without time zone from database."
1330:                       end
1331:                       Time.local($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, $8.to_i)
1332:                     elsif data_type == "timestamptz"
1333:                       unless value_string =~ /^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]*))?([+-][0-9]{2})$/
1334:                         aise "Unexpected format for timestamp with time zone from database."
1335:                       end
1336:                       (Time.utc($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, $8.to_i) - (3600 * $9.to_i)).localtime
1337:                     else
1338:                       value_string
1339:                     end
1340:                   else
1341:                     value_string
1342:                   end
1343:                 end
1344:               end
1345:               result << record_class.new(record_data, true)
1346:             end
1347:             return result
1348:           else
1349:             @backend_connection.async_exec(command)
1350:             return nil
1351:           end
1352:         end
1353:       rescue PGError
1354:         raise FlexiRecord::DatabaseError, $!.message
1355:       end
1356:     end